Δευτέρα 8 Μαΐου 2017

Αντικείμενο Ομάδα (Πώς λειτουργεί)

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


Για να δούμε την ομάδα θα πρέπει να δούμε πως καταχωρούνται τμήματα και μεταβλητές από το διερμηνευτή.




Υπάρχουν δυο λίστες, μια η λίστα μεταβλητών και μια η λίστα τμημάτων/συναρτήσεων. Κάθε λίστα έχει δυο μέρη, το ένα είναι το ευρετήριο βάσει κλειδιού και το άλλο ο πίνακας τιμών. Οι λίστες είναι δυναμικές, αλλά δεν μπορούμε να διαγράψουμε οπουδήποτε αλλά μόνο από το τέλος. Στο τέλος είναι το πιο πρόσφατο δημιουργημένο. Το κλειδί ευθύνεται για το πώς κάτι είναι γενικό ή ανήκει κάπου. Το κλειδί λέγεται και ισχνή αναφορά εδώ.

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

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

Στο σχήμα φαίνεται και ο σωρός τιμών. Τα τμήματα παρέχουν το δικό τους σωρό στα τμήματα που καλούν ενώ οι συναρτήσεις πάντα ξεκινούν με νέο με αρχικές τιμές τα ορίσματα σε αυτές. Οι σωροί είναι αντικείμενα.

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

Όταν θέλουμε να ορίσουμε ένα τμήμα απλά το γράφει ο διερμηνευτής στο πίνακα τμημάτων/συναρτήσεων και μαζί με το όνομα του τμήματος που το δημιούργησε (το οποίο γνωρίζει το αντικείμενο εκτέλεσης) μπαίνει ένα κλειδί στο ευρετήριο. Αν σε ένα τμήμα ορίσουμε ένα γενικό τμήμα, πάλι θα μπει και αυτό στον ίδιο χώρο, απλά στο όνομα του ευρετηρίου θα μπει το όνομα του τμήματος που ορίζουμε ως γενικό χωρίς πρόθεμα το όνομα του τμήματος. Το ευρετήριο δέχεται όμοια κλειδιά αλλά στην αναζήτηση δείχνει πάντα το τελευταίο που μπήκε. Με αυτόν τον τρόπο μια γενική μπορεί να σκιάσει μια υπάρχουσα γενική με το ίδιο όνομα (για όσο το αντικείμενο εκτέλεσης εκτελείται).

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

Στη λίστα μεταβλητών έχουμε την περίπτωση να έχουμε περισσότερες μεταβλητές από τις τιμές που δίνονται γι´ αυτές στο πίνακα τιμών. Αυτό μπορεί να συμβεί αν έχουμε μεταβλητές που είναι αναφορές σε άλλες. Η αναφορά δηλώνεται εσωτερικά ως τη θέση σε υπάρχον τιμή στο πίνακα τιμών. Επιπλέον στο ευρετήριο δηλώνεται ότι έχουμε αναφορά ώστε στην αποκατάσταση της λίστας (στο τέλος εκτέλεσης του τμήματος) να μην διαγραφεί η τιμή όπου δηλώνεται ότι είναι αναφορά.


Ο σωρός τιμών δεν έχει ονόματα, που σημαίνει ότι όταν βάζουμε το Α θα μπεί η τιμή του. Επειδή όμως χρησιμοποιείται για τις κλήσεις τμημάτων και συναρτήσεων, στο πέρασμα με αναφορά, το &Α θα γραφτεί ως ισχνή αναφορά. Στο διάγραμμα γράφει ότι τα ονόματα στην λίστα μεταβλητών λέγονται ισχνές αναφορές. Όταν μια Διάβασε στο τμήμα που καλέσαμε ζητάει έστω το &Χ τότε περιμένει να βρει ένα αλφαριθμητικό, και αυτό να του δώσει το δείκτη (τη θέση) στο πίνακα τιμών. Αν δεν συμβεί αυτό βγαίνει λάθος. Αν συμβεί τότε δημιουργείται μια  Χ ως αναφορά του Α (του προηγούμενου τμήματος), χωρίς να δημιουργηθεί νέα τιμή στο πίνακα τιμών.

Η ιδέα του αντικειμένου Ομάδα αρχικά ήταν να μπορούμε να δίνουμε με αναφορά μια ομάδα μεταβλητών, δηλαδή να περνάμε ένα αντικείμενο με μια λίστα ισχνών αναφορών. Η δημιουργία ομάδας στην ουσία είναι δημιουργία μεταβλητών και ενός αντικειμένου που λέει ποιες μεταβλητές συνιστούν την ομάδα. Στο ευρετήριο τα ονόματα των μεταβλητών παίρνουν ένα διπλό πρόθεμα, το όνομα από το τμήμα που ανήκουν και το όνομα της ομάδας. Ως τοπικές μεταβλητές στο τμήμα εμφανίζονται μόνο με το μισό πρόθεμα, το όνομα ομάδας. Έτσι η Ομάδα Άλφα {Χ=10, Υ=3} θα έχει τα Άλφα.Χ και Άλφα.Υ ως τοπικές μεταβλητές στο τμήμα που δημιουργήσαμε το Άλφα.

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

Σε επόμενο βήμα οι ομάδες απέκτησαν τμήματα και συναρτήσεις. Και αυτά γράφονται ως ανεξάρτητες οντότητες στην λίστα τμημάτων/συναρτήσεων με πρόθεμα το όνομα του τμήματος και το όνομα της ομάδας. Όμως εδώ ο πίνακας για το κώδικα έχει και ένα πεδίο ακόμα που γράφει το όνομα της ομάδας (ως ισχνή αναφορά). Όταν εκτελούμε ένα τμήμα ομάδας ο διερμηνευτής ετοιμάζει ένα αντικείμενο εκτέλεσης και το ενημερώνει ότι είναι τμήμα της ομάδας με συγκεκριμένη ισχνή αναφορά. Ας υποθέσουμε ότι η ομάδα έχει μια μεταβλητή Χ. Αν εμφανιστεί το  .Χ (δείτε την τελεία πριν το Χ) ή το Αυτό.Χ (είναι το ίδιο πράγμα), σε μια έκφραση τότε αυτόματα ο διερμηνευτής θα τον αναζητήσει βάζοντας ως πρόθεμα όχι το όνομα του τμήματος αλλά την ισχνή αναφορά στο αντικείμενο. Έτσι θα διαβάσει την τιμή της μεταβλητής Χ της ομάδας. Στην εκχώρηση τιμής πρέπει να δώσουμε το <= και όχι το = γιατί το δεύτερο φτιάχνει πάντα τοπικές μεταβλητές (αν χρειαστεί να ορίσει, πράγμα που δεν το κάνει στους πίνακες, αφού ορίζονται με την Πίνακας).

Ας δούμε όμως μια λειτουργία που αλλάζει την υπόσταση της ομάδας. Ουσιαστικά την αλλάζει σε αντίγραφο. Η βασική υπόσταση είναι το ανοικτό αντικείμενο, όπου όλα τα μέλη είναι στις λίστες, και μπορούν να βρεθούν άμεσα από τον διερμηνευτή. Η άλλη υπόσταση είναι το κλειστό αντικείμενο. Εκεί η ομάδα έχει σε δική της λίστα όχι μόνο ονόματα αλλά και τιμές, και δεν έχει κανένα μέλος στο πίνακα τιμών ή στο πίνακα κώδικα. Μια ομάδα ως κλειστό αντικείμενο δεν βρίσκεται καν σε ευρετήριο, γιατί δεν έχει όνομα. Μπορεί να βρίσκεται ως τιμή σε πίνακα, και άλλα αντικείμενα που δέχονται αντικείμενα (όπως η Κατάσταση και ο Σωρός),  στο σωρό τιμών του τμήματος/συνάρτησης (είναι και αυτός αντικείμενο Σωρός), και στην επιστροφή από παράσταση (ή αλλιώς τη λέμε δεξιά έκφραση, δεξιά του ίσον).

Άλλες γλώσσες προγραμματισμού δουλεύουν με αυτό που λέμε εδώ κλειστό αντικείμενο, ως αντικείμενο. Επίσης σε κάποιες γλώσσες το τι θα έχει ένα αντικείμενο το προδιαγράφει μια κλάση, η οποία με έναν τρόπο είναι συνδεδεμένη με τη κάθε νέα παρουσία αντικειμένου αυτής της κλάσης. Επειδή στη Μ2000 τα αντικείμενα είναι λίστες μελών δεν μας ενδιαφέρει να έχουν σύνδεση με προκαθορισμένη λίστα μελών, που προφανώς θα ήταν ένα άλλο αντικείμενο, και ίσως η όποια αλλαγή του άλλαζε όλα τα συνδεδεμένα αντικείμενα. Μπορούμε να έχουμε μια συνάρτηση να επιστρέφει αντικείμενο όπως το θέλουμε, ως κατασκευαστής αντικειμένων.  Τεχνικά τα αντικείμενα Ομάδα έχουν κοινή διεπαφή την οποία χειρίζεται ο διερμηνευτής. Προγραμματιστικά το κοινό το δημιουργεί ο τρόπος που φτιάχνουμε ομάδες. Μπορεί να φτιαχτεί μια ομάδα βηματικά (να προσθέτουμε) ή με αλλαγές (να αλλάζουμε κώδικα σε τμήματα ή συναρτήσεις της ομάδας), να προσθέσουμε κάτι πρόσκαιρα και να διαγράψουμε μετά (δεν θα φανεί αυτό σε αυτό το κείμενο). Πάντα θα βλέπουμε την ομάδα σαν μια οντότητα, με δικά της μέλη και όχι με δικό της τύπο. Ο τύπος εννοείται! Θα μπορούσε κανείς να βάζει μια μεταβλητή Τύπος$ και να γράφει το όνομα τύπου!

Καλύτερα όμως να έχουμε έναν κατασκευαστή που να φαίνεται ότι είναι ο τύπος.  Η εντολή Κλάση στην Μ2000 δημιουργεί μια συνάρτηση (γενική εκτός ομάδας, τοπική εντός ομάδας) που επιστρέφει μια ομάδα (ως κλειστό αντικείμενο, γιατί όπως αναφέρθηκε η επιστροφή από δεξιά έκφραση, όπως το =Κλάση1() είναι κλειστό αντικείμενο.



\\ αυτό το γράφουμε έστω στο τμήμα Β
Γενική Μ=30
Τμήμα Γενικό Α {
      \\ το τμήμα δεν θα έχει πρόθεμα το γονικο τμήμα
      \\ άρα θα είναι γενικό
      \\ Εντός όμως της Α δεν μπορεί να κληθεί
      \\ Δεν έχει αναδρομή το τμήμα με την απλή κλήση με το όνομα
      \\ Έχει αν κληθεί με την Κάλεσε Α
      \\ Οι συναρτήσεις έχουν αναδρομή.
      Ομάδα Άλφα {
            Χ=10
            Τμήμα Α {
                  Διάβασε Κ
                  Τύπωσε Κ * .Χ
                  .Χ<=Κ
            }
            Συνάρτηση Β (Ν){
                  \\ ο διερμηνευτής θα βάλει τη εντολή: Διάβασε Ν
                  \\ κατά την εγγραφή της συνάρτησης στη λίστα
                  =.Χ**Ν
            }
      }
      Πίνακας Α(10)
      Λίστα !
      Τμήματα ?
      Α(3)=Άλφα
      Α(3).Α 30
      \\ άλλαξε η τιμή της Χ στο Α(3)
      Τύπωσε Α(3).Χ, Άλφα.Χ
      Τύπωσε Τύπος$(Α(3)) \\ Group δηλαδή Ομάδα
}
Λίστα !
Τμήματα ?
Α    \\ καλούμε το Α μόνο με το όνομα





Αν το ανοικτό αντικείμενο (αν έχει όνομα είναι ανοικτό) Άλφα το δώσουμε ως τιμή σε νέο όνομα έστω Βήτα τότε ο διερμηνευτής πρώτα παράγει ένα κλειστό αντικείμενο με αντιγραφές όλων των μελών του Άλφα, για να βγάλει την δεξιά έκφραση, και μετά παράγει το Βήτα ως ομάδα, με όλα τα μέλη που δηλώνει το κλειστό αντικείμενο και το πετάει. Μετά το Βήτα=Άλφα θα υπάρχουν δυο ομάδες με ίδιες τιμές, αλλά όχι αναφορές του Άλφα στο Βήτα. Μπορούμε δηλαδή να αλλάζουμε τιμές σε όποιο θέλουμε.
Αν δίναμε την εντολή Ένωσε Άλφα στο Βήτα τότε θα είχαμε ένα Βήτα με όλα τα μέλη σε αναφορά στο Άλφα. Το ίδιο θα γίνονταν αν δίναμε Βάλε &Άλφα και μετά το Διάβασε &Βήτα. Και στις δυο περιπτώσει το Βήτα πρέπει να είναι νέο όνομα (να μην έχει χρησιμοποιηθεί στο ίδιο τμήμα/συνάρτηση,  γιατί όπως αναφέρθηκε μια μεταβλητή με αναφορά δεν μπορεί να πάρει άλλη αναφορά, ενώ οποιαδήποτε μεταβλητή, ακόμα και αυτή που είναι αναφορά σε άλλη μπορεί να δώσει νέα αναφορά, σε νέο όνομα).

Συγχώνευση

Μια λειτουργία που δεν έχει φανεί ακόμα είναι η συγχώνευση ομάδας. Αν το Βήτα είναι ήδη ομάδα τότε το Βήτα=Άλφα θα εκτελεστεί ως εξής: Θα δημιουργηθεί το κλειστό αντικείμενο του Άλφα και θα συγχωνευθεί στο Βήτα. Αν υπάρχουν μέλη με ίδιο όνομα τότε το Βήτα θα αλλάξει τιμές σε αυτά, αν όχι τότε το Βήτα θα τα αποκτήσει!

Θέση σε Πίνακα

Αν έχουμε τον πίνακα Α(10) (με δέκα στοιχεία και έστω με Βάση 0, με θέσεις από 0 έως 9), τότε με την Α(0)=Άλφα βάζουμε το κλειστό αντικείμενο στο Α(0). Αν υπήρχε ένα άλλο ήδη στην θέση αυτή θα διαγραφεί και θα μπει το νέο.
Οι πίνακες είναι αντικείμενα στην Μ2000. Στην λίστα μεταβλητών κάθε πίνακας πιάνει μια θέση. Για το λόγο αυτό δεν μπορούμε να έχουμε αναφορά σε θέση πίνακα (αφού αναφορές γίνονται μόνο σε ότι είναι στο ευρετήριο). Μπορούμε όμως να έχουμε αναφορά σε όλο το πίνακα. Κάθε στοιχείο πίνακα (κάθε θέση αν το πούμε αλλιώς) εσωτερικά είναι τύπου Variant, που σημαίνει ότι μπορεί να είναι αριθμός, αλφαριθμητικό ή αντικείμενο. Έτσι ενώ δημιουργούμε πίνακα για αριθμούς μπορούμε να βάλουμε αντικείμενα στις θέσεις του.

Μια ομάδα επιστρέφει εκτός από το κλειστό αντικείμενο και το μηδέν σε εκφράσεις. Το αντικείμενο που μένει μπορεί να το χρησιμοποιήσει ο διερμηνευτής σε εκχώρηση. Ειδικά στις τελευταίες εκδόσεις της γλώσσας τα αντικείμενα μπορούν να πάρουν Αξία, μια συνάρτηση Αξία { } που επιστρέφει κάποια τιμή. Σε αυτήν την περίπτωση το αντικείμενο Ομάδα δεν επιστρέφει κλειστό αντικείμενο αλλά τιμή. Η συνάρτηση Ομάδα() παίρνει μια ομάδα και είτε αυτή γυρνάει το κλειστό αντικείμενο ή μια τιμή, δίνει πάντα το κλειστό αντικείμενο.

Εκτός από τα Τμήματα και τις Συναρτήσεις μπήκαν στις ομάδες και οι Τελεστές. Οι τελεστές δουλεύουν όταν ο διερμηνευτής βρίσκει ομάδα. Αν έχουμε Αξία τότε δεν βρίσκει ομάδα ο διερμηνευτής αλλά την αξία. Βρίσκει όμως σε αριστερή έκφραση (αριστερά του =), ή αν έχουμε ανοικτό αντικείμενο τότε βρίσκει αν έχουμε το Ομάδα(Άλφα) οπότε λειτουργεί ο τελεστής.

Οι ομάδες μπορούν να έχουν όνομα αλφαριθμητικής μεταβλητής. Σε αυτή την περίπτωση μπορούμε να παίρνουμε τιμή από την ομάδα αλφαριθμητικό, ή αν θέλουμε να δίνουμε τιμή αλφαριθμητικό. Το τι ακριβώς θα κάνουμε την τιμή το περιγράφουμε στη Θέσε {}, και ομοίως το πώς εξάγεται η τιμή από την ομάδα το περιγράφουμε με την Αξία {}.

Μια ομάδα μπορεί να έχει δημόσια ή και ιδιωτικά μέλη. Τα ιδιωτικά μέλη δεν εμφανίζονται στο τμήμα, παρά μόνο εντός της ομάδας. Αφού όμως είδαμε ότι όλα τα μέλη είναι ανεξάρτητα, τότε το ερώτημα που προκύπτει είναι "πώς κρύβονται"; Λοιπόν το κρύψιμο είναι εύκολο γιατί απαιτείται ένας χαρακτήρας πριν από το όνομα του μέλους να δηλώνει ότι είναι κρυφό, και τον βάζει αυτόν στον ορισμό του μέλους, αφού δηλωθεί μετά την ετικέτα Ιδιωτικό:. Όταν εντός ενός τμήματος ή μιας συνάρτησης που συνδέεται με μια ομάδα αναζητούμε την .Χ που είναι κρυφή τότε ο διερμηνευτής τη ζητάει ως φανερή και  δεν θα την βρει, οπότε την ζητάει ως κρυφή (βάζει το χαρακτήρα που το δηλώνει), και έτσι τη βρίσκει!

Όταν μια ομάδα έχει άλλες ομάδες στην ουσία έχει για κάθε περιεχόμενη ομάδα ένα αντικείμενο ομάδα και τις μεταβλητές χωριστά (όσο είναι ανοικτό), ενώ όταν έχουμε κλειστό αντικείμενο, όλα αυτά βρίσκονται στην λίστα της ομάδας που περιέχει τις άλλες. Ένα τμήμα περιεχόμενης ομάδας σε ομάδα βλέπει μόνο τις μεταβλητές τις δικές του και της ομάδας του, αλλά όχι της ομάδας που περιέχεται η ομάδα του. Μπορεί να δει όμως τις μεταβλητές που περιέχονται σε ομάδες που περιέχει η ομάδα του (αρκεί να μην είναι ιδιωτικές).

Στις νεότερες εκδόσεις υπάρχουν οι Ιδιότητες, που είναι ομάδες με τιμές, και ορίζουμε αν θα έχουν τις συναρτήσεις αξία ή και θέσε (αν θα δίνουν ή και παίρνουν τιμή). Παράλληλα μπορούμε να ορίσουμε ιδιότητες σε ιδιότητες (αφού είναι ομάδες σε ομάδες), τμήματα και συναρτήσεις. Το πρόβλημα που ίσως να μην φάνηκε στην προηγούμενη παράγραφο, επιλύθηκε εδώ, με μια ειδική ένωση μεταβλητής με μεταβλητή στη γονική ομάδα. (ενώ κανονικά δεν μπορούμε να δούμε τη μεταβλητή της γονικής ομάδας, μέσω ειδικής εντολής γίνεται). Αυτή η εντολή δουλεύει με χρήση του αντικειμένου εκτέλεσης (διότι το τμήμα της ομάδας έχει δικό του αντικείμενο εκτέλεσης και υπάρχει τρόπος να δούμε μεταβλητές στο γονικό αντικείμενο, εκεί που υπάρχει η ομάδα και η γονική ομάδα). Η ιδιότητα ως εντολή ορισμού δημιουργεί μια κρυφή μεταβλητή στην ομάδα και φτιάχνει μια ομάδα που χειρίζεται αυτήν την μεταβλητή (με χρήση της ειδικής ένωσης). Έτσι αν μια ιδιότητα οριστεί να έχει μόνο αξία, να επιστρέφει δηλαδή μόνο τιμή, άρα να μην δέχεται τιμή (να μην γίνεται εκχώρηση), δεν σημαίνει ότι δεν μπορεί μέσα από την ομάδα που έχει την ιδιότητα να αλλάξει τιμή, απλά αλλάζουμε τιμή στην κρυφή μεταβλητή.

Σε μια Ιδιότητα Βήτα {Αξία}=10 φτιάχνεται μια [Βήτα] με τιμή 10. Σε ένα τμήμα της ομάδας που περιέχει την Βήτα μπορούμε να δούμε την .Βήτα ως μόνο για ανάγνωση και την .[Βήτα] για ανάγνωση και εγγραφή. Έξω όμως από την ομάδα η [Βήτα] δεν υπάρχει, είναι κρυφή. Οι ιδιότητες είναι πάντα δημόσιες (ενώ οι πραγματικές τους μεταβλητές είναι ιδιωτικές). Μπορούμε να μην χρησιμοποιήσουμε την κρυφή μεταβλητή και να φτιάξουμε ιδιότητες απευθείας με την εντολή Ομάδα και όπως τις θέλουμε, ή να χρησιμοποιήσουμε το Αξία {} και Θέσε {} εντός του ορισμού της ιδιότητας και να κάνουμε κάποιους υπολογισμούς για το πώς θα διαμορφωθεί η τελική τιμή, ή πώς θα διαμορφωθεί η εκχώρηση. Τέλος οι ιδιότητες μπορούν να δέχονται και δείκτες, έτσι μια ιδιότητα Χ μπορεί να έχει δείκτη στην εισαγωγή, ή και στην εξαγωγή τιμής.


Εδώ έχουμε ένα παράδειγμα με μια ομάδα ως μια ιδιότητα. Παίρνει τιμή με δείκτη, και δίνει τιμή με δείκτη. Ο διερμηνευτής ένα Βήτα( θα το ψάξει πρώτα ως πίνακα και αν δεν το βρει ως ομάδα Βήτα (αν δεν την βρει τότε κάνει αναζήτηση ρουτίνας γιατί οι ρουτίνες καλούνται με τη Διαμέσου ή χωρίς αυτήν με όνομα και παρενθέσεις, με ή χωρίς ορίσματα). Εδώ θα το βρει ως ομάδα, θα δει ότι έχει τη θέσε (τη βλέπει από μια σημαία μέσα στο αντικείμενο), θα δει ότι η θέσε έχει παραμέτρους και θα περάσει τα ορίσματα στο σωρό, μετά θα βάλει στο σωρό το αποτέλεσμα της έκφρασης  και θα καλέσει την Θέσε. Εδώ διαβάζουμε το .Μ (που είναι κρυφή στην Βήτα) και την διαιρούμε με τον δείκτη.

Ομάδα Βήτα {
Ιδιωτικό:
      Μ
Δημόσιο:
      Αξία (χ) {
            =.Μ*Χ
      }
      Θέσε (χ) {
           Διάβασε .Μ
           .Μ/=Χ
      }
}
βήτα(2)=10
Τύπωσε βήτα(2), βήτα(4)
βήτα(10)=2
Τύπωσε βήτα(2), βήτα(4), βήτα(10)



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

Ομάδα Άλφα {
      Κ=10, Λ=30
      Αξία {
            =.Κ*.Λ
      }
      Συνάρτηση Αυτό {
            =Ομάδα(Αυτό)
      }
      Τελεστής "+" {
            Διάβασε Μ \\ ομάδα
            .Κ+=Μ.Κ
            .Λ+=Μ.Λ
      }
      Τελεστής "+=" {
            Διάβασε Μ \\ αριθμός
            .Κ+=Μ
            .Λ+=Μ
      }
      Τελεστής ">" {
            Διάβασε Μ \\ ομάδα
            Βάλε Μ.Κ>.Κ και Μ.Λ>.Λ
      }
      Θέσε {
            Αν Ταύτιση("Ο") τότε {
                  Διάβασε Αυτό
             \\ ή κάνουμε επιλεκτική συγχώνευση
             \\ σε τιμές
             \\  .Κ<=Μ.Κ
             \\  .Λ<=Μ.Λ
            } Αλλιώς Λάθος "Περίμενα Ομάδα"
   
      }
}
Τύπωσε Άλφα
Βήτα=Άλφα.Αυτό()
Τύπωσε Βήτα.Αυτό()>Άλφα.Αυτό()
Βήτα+=10
Δέλτα=Αλφα.Αυτό()+Βήτα.Αυτό()
Τύπωσε Δέλτα, Αλφα+Βήτα
Τύπωσε (Άλφα.Κ+Βήτα.Κ)*(Άλφα.Λ+Βήτα.Λ), (Άλφα.Κ*Αλφα.Λ)+(Βήτα.Κ*Βήτα.Λ)
Τύπωσε Βήτα.Αυτό()>Άλφα.Αυτό()
Τύπωσε Βήτα>Άλφα, Βήτα, Άλφα
Βήτα=Άλφα.Αυτό()
Τύπωσε Βήτα>Άλφα, Βήτα, Άλφα
 

Δείτε ότι στην σύγκριση η Μ είναι η ομάδα αριστερά του > και εδώ βάζουμε στο σωρό μια τιμή. Στο τελεστή "+" δεν βάζουμε κάτι και βάζει ο διερμηνευτής το "Αυτό". Στην "+=" ο τελεστής επιδρά στο αντικείμενο αριστερά του, ενώ στο "+" δεν επιδρά σε κανένα, γιατί στην δεξιά έκφραση έχουμε κλειστά αντικείμενα που ανοίγει πρόσκαιρα ο διερμηνευτής.

Οι συναρτήσεις των Τελεστών βλέπουν το σωρό του τμήματος που είναι η έκφραση που περιέχονται. Δεν υπάρχει το =τιμή_οποιαδήποτε που θα είχε μια κανονική συνάρτηση ως επιστροφή τιμής. Ο τύπος κλήσης είναι παρόμοιος με το Κάλεσε Συνάρτηση1() όπου και εδώ δεν έχουμε επιστροφή τιμής και ο σωρός είναι ο σωρός του τμήματος/συνάρτησης που εκτελεί αυτή την εντολή.


Στο blog αυτό υπάρχουν πολλά παραδείγματα με ομάδες, που χρησιμοποιούνται σε πίνακες. Αν ένας πίνακας δηλωθεί ότι έχει μια συγκεκριμένη ομάδα τότε ο διερμηνευτής βάζει τα τμήματα, τις συναρτήσεις, και τους τελεστές σε μια ξεχωριστή θέση στο αντικείμενο πίνακα, και όλα τα κλειστά αντικείμενα έχουν μια μετατροπή που έμμεσα βλέπουν αυτή τη θέση. Έστω στον Α() έχουμε όλες τις θέσεις με ομάδες με κοινά τμήματα/συναρτήσεις/τελεστές, και στο Β() έχουμε απλά αριθμούς (πχ το 0). Η Β(3)=Α(2) θα μετατρέψει το Β(3) σε ομάδα, και θα έχει ένα αντίγραφο του Α(2), μαζί όμως με τα τμήματα/συναρτήσεις/τελεστές.


Στο παράδειγμα χρησιμοποιώ μια κλάση (μια συνάρτηση που γυρνάει ομάδα), και εκεί έχω δηλώσει την ΡιζαΧ ως ιδιότητα μόνο για ανάγνωση. Συνδέω το γονικό Χ με μια τοπική Χ και δίνω στην Αξία το Ρίζα(Χ). Η κρυφή μεταβλητή [ΡίζαΧ] δεν χρησιμοποιείται. Εξ ορισμού οι πίνακες έχουν βάση 0. Μπορεί να αλλάξει με την εντολή Βάση 1 ή πρόσκαιρα μετά την Πίνακας...πχ Πίνακας Βάση 1, Α(10)=1 θα δώσει το Α(1)...Α(10) με 1 το καθένα.

Κλάση Άλφα {
Ιδιωτικό:
      Χ=10
Δημόσιο:
      Τμήμα ΔείξεΧ {
            Τύπωσε .Χ
      }
      Ιδιότητα ΡίζαΧ {
            Αξία {
                  Ένωσε Γονικό Χ στο Χ
                  Αξία=Ρίζα(Χ)
            }
      }
      Θέσε {
            Διάβασε .Χ
      }
}
Πίνακας Α(10)=Άλφα(), Β(5)=100
Β(
3)=Α(5)
Τύπωσε Β(3).ΡίζαΧ, Β(4)
Α(
5)=20
Τύπωσε Α(5).ΡίζαΧ
\\ η Στη κάνει αυτό Βάλε Β(3) : Διάβασε Α(5)
\\ Α(5)=Β(3) θα έδινε ομάδα αντί για αριθμό στο .Χ
Στη Α(5)=Β(3)
Τύπωσε Α(5).ΡίζαΧ









Κυριακή 7 Μαΐου 2017

Αναθεώρηση 18 (Έκδοση 8.7)

Σε αυτήν την αναθεώρηση διορθώθηκε η Έξοδος Για, η έξοδος από μια δομή Για Επόμενο.  Αυτή η αναθεώτηση προέκυψε από έλεγχο συμβατότητας που διενεργώ συχνά, και εδώ τρέχοντας το πρόγραμμα αυτό

Όλοι οι πιθανοί τρόπο για να διακόψουμε μια Για  {} ή μια Για Επόμενο:
Περιπτώσεις με Για Επόμενο

Για ι=1 έως 100 : Τύπωσε ι : Επόμενο ι
Για κ=1 έως 10
      Αν κ>5 τότε έξοδος για
      Τύπωσε κ
Επόμενο κ
Για κ=1 έως 10
      Αν κ>5 τότε έξοδος για 300
      Τύπωσε κ
Επόμενο κ
Τύπωσε "δεν το βλέπεις αυτό"
300 Τύπωσε "Έξοδος προς αριθμό γραμμής"
Για κ=1 έως 10
      Αν κ>5 τότε έξοδος για αλφα
      Τύπωσε κ
Επόμενο κ
Τύπωσε "δεν το βλέπεις αυτό"
\\ πρέπει το αλφα να είναι ακριβώς με πεζά/κεφαλαία/τόνους
\\ όπως δηλώνεται εδώ, αλλιώς η έξοδος θα είναι για όλο το τμήμα.
αλφα:
Τύπωσε "Έξοδος προς ετικέτα"

Περίπτώσεις με Για { }

Για ι=1 έως 100 {Τύπωσε ι }
Για κ=1 έως 10 {
      Αν κ>5 τότε έξοδος
      Τύπωσε κ
}
Για κ=1 έως 10 {
      Αν κ>5 τότε 300
      Τύπωσε κ
}
Τύπωσε "δεν το βλέπεις αυτό"
300 Τύπωσε "Έξοδος προς αριθμό γραμμής"
Για κ=1 έως 10 {
      Αν κ>5 τότε προς αλφα
      Τύπωσε κ
}
Τύπωσε "δεν το βλέπεις αυτό"
\\ πρέπει το αλφα να είναι ακριβώς με πεζά/κεφαλαία/τόνους
\\ όπως δηλώνεται εδώ, αλλιώς η έξοδος θα είναι για όλο το τμήμα.
αλφα:
Τύπωσε "Έξοδος προς ετικέτα"


Περιπτώσεις όπου θέλουμε να συνεχίσει η μέτρηση αλλά να μην εκτελεστούν όλες οι εντολές εντός της Για.
Αν το επόμενο ι είναι το τελευταίο τότε θα πάμε στο Επόμενο κ και αν είναι το τελευταίο τότε θα κάνουμε έξοδο στο 200. Παρόλο που δεν βλέπουμε μπλοκ η Για Επόμενο χρησιμοποιεί μπλοκ από το σημείο που ξεκινάει μέχρι το τέλος του κώδικα! Απλά δεν ξέρει πότε τελειώνει ο κώδικάς της, πράγμα που η Για {} ξέρει επακριβώς.  Η αν ι<2 Συνέχισε μπορεί να μπει και στη Για Επόμενο αλλά θα προκύψει λάθος στην εκτέλεση, σε άλλο σημείο, αν το ι δεν γίνει ποτέ >=2, και έτσι να μπορεί να εκτελεστεί το Επόμενο ι.
Γενικά σε τέτοιες περιπτώσεις το Για {} είναι καλύτερο (είναι και σχεδόν δυο φορές ταχύτερο από το Για Επόμενο). Η εντολή Συνέχισε δεν ανήκει στη Για {} αλλά έχει δυο εκδοχές, ως Συνέχισε εντός ενός μπλοκ, και ως Συνέχισε εντός ενός μπλοκ σε μια Επίλεξε Με /Τέλος Επιλογής, όπου του λέει να εκτελέσει τη "ροή" όπως θα ήταν αν είχε τερματίσει σε αυτό το σημείο το Με (Η Επίλεξε Με μπορεί να εκτελεί ένα Με ή μια σειρά Με, με χρήση των Διέκοψε και Συνέχισε)


Για κ=1 έως 2
      Για ι=1 έως 2
            Τύπωσε "11111"
            Αν ι <2 τότε Επόμενο ι : Επόμενο κ: Προς 200
            Τύπωσε "22222222"
      Επόμενο ι
Επόμενο κ
200
Τύπωσε "Οκ"
Για κ=1 έως 2 {
      Για ι=1 έως 2 {
            Τύπωσε "11111"
            Αν ι <2 τότε Συνέχισε
            Τύπωσε "22222222"
      }
}
Τύπωσε "Οκ"


Απαρίθμηση με μπλοκ εντολών. Εδώ σχηματίζουμε τη δομή! Η εντολή Κυκλικά απλά σημαδεύει το μπλοκ για επανάληψη και αυτή συμβαίνει όταν τερματίσει το μπλοκ (στο άγκιστρο). Η εντολή Συνέχισε πάει άμεσα στο τέλος, και αν έχουμε τη σημαία "κυκλικά" τότε κάνει άμεσα επαννεκίνηση του μπλοκ, ενώ αν όχι τότε συνεχίζουμε εκτός μπλοκ


ι=1
{
      κ=1
      {
            Τύπωσε κ,
            κ+=1
            Αν κ<=ι τότε κυκλικά
      }
      Τύπωσε
      ι+=1
      Αν ι<=5 τότε κυκλικά
}

Άλλο παράδειγμα (εδώ με ακύρωση=αληθές απλά θα κάνει το ι=1 και μετά η συνέχισε θα εγκαταλείψει το μπλοκ):

'ακύρωση=ψευδές
ακύρωση=αληθές
ι=0
{
      Αν όχι ακύρωση τότε κυκλικά
      ι++
      Αν ι< 5 τότε συνέχισε
      Τύπωσε ι
      Αν ι>=10 τότε έξοδος
}






Παρασκευή 5 Μαΐου 2017

Παράδειγμα (γράφτηκε σε Linux με Wine)

Το πρόγραμμα (άσκηση) γράφτηκε απευθείας σε Μ2000 που έτρεχε σε Linux με Wine.
Η εξαγωγή σε html έγινε απευθείας από το διορθωτή της Μ2000 με ctrl+C, με αντιγραφή (κάνει την μετατροπή στο κείμενο που επιλέγουμε - με ctrl+A το επιλέγουμε όλο). Για να το βάλω σε αυτό το blog όμως το επικολλώ πρώτα σε Libbreoffice Writer και μετά κάνω αντιγραφή από αυτό και επικόλληση εδώ στο blog. Σε Windows σύστημα δεν χρειάζεται κάποιος επεξεργαστής κειμένου, δουλεύει απ' ευθείας (αν από Wine κάνουμε απευθείας επικόλληση δεν θα βγει με χρώμα το κείμενο, και προφανώς εδώ κάτι παίζει με τον Firefox σε Ubuntu).
Η χρησιμότητα του προγράμματος είναι για να μάθουμε, να το πειράξουμε κιόλας, και να δούμε τι θα βγάλει!
Πρώτα πειράζουμε ότι είναι σταθερές, δηλαδή νούμερα και κείμενα (αλφαριθμητικά)! Κάποια νούμερα είναι χρώματα, κάποια όμως έχουν συγκεκριμένη λειτουργία, άλλες φορές δηλώνουν μια επιλογή τρόπου εκτέλεσης, και άλλες φορές τιμές για τη συγκεκριμένη επιλογή, όπως στην Αναφορά μια από αυτές είναι το κείμενο και μια άλλη το πλάτος εμφάνισης.
Δοκιμάστε χρώματα, άλλα κείμενα.
Η Αντίγραψε αντιγράφει απευθείας στην οθόνη από την οθόνη, απλά εδώ την βάζουμε να αντιγράφει σε αλφαριθμητικό. Εκτός από την περίπτωση που δίνουμε όνομα και σώνει όλη τη οθόνη σε αρχείο, στις άλλες παίρνει ως αριστερή πάνω γωνία την θέση του δρομέα, και έτσι δίνουμε το πλάτος και το ύψος που θέλουμε, και αν δεν το δώσουμε σε αλφαριθμητικό τότε θα δώσουμε δυο ακόμα νούμερα, το σημείο που θέλουμε να βγει το αντίγραφο (την πάνω αριστερή γωνία του προορισμού).
Η εντολή εικόνα κάνει κάτι άλλο. Παίρνει αρχείο ή αλφαριθμητικό με εικόνα και μπορεί να εμφανίσει την εικόνα με το πλάτος που θέλουμε (και βρίσκει το ύψος μόνη της), ή να δώσουμε πλάτος και ύψος (άρα να χαλάσουμε τις αρχικές αναλογίες. Και οι δυο εντολές έχουν και άλλες παρόμοιες λειτουργίες. Θα τις δούμε άλλη φορά!

Δείτε στις εικόνες ότι η φόρμα της Ρώτα() έχει διαφορετικό μέγεθος. Οι έτοιμες φόρμες διαλόγων της Μ2000 έχουν την δυνατότητα να μεγαλώνουν ή να μικραίνουν χωρίς να αλλάζει αυτό που δείχνουν.
Επίσης δείτε ότι με την χρήση του αλφαριθμητικού που κρατάει εικόνα δώσαμε την εικόνα στην φόρμα εισαγωγής!
Η έτοιμη εικόνα στη Ρώτα εμφανίζεται με μαύρο φόντο, ενώ σε Windows με διάφανο! (έχει θέμα το Wine)
Στην δεύτερη εικόνα η εντολή Φόντο 5,0 έβαλε φόντο από Ματζέντα μέχρι Μαύρο, υπολογίζοντας αυτόματα όλα τα ενδιάμεσα.
Επίσης φαίνεται ένα μαύρο περιθώριο (σε αυτό μπορούμε να αλλάξουμε χρώμα, και να το χρησιμοποιήσουμε και σαν οθόνη, να γράψουμε δηλαδή, αλλά εδώ δεν μας απασχολεί καθόλου).





\\ Στην άσκηση αυτή βλέπουμε:
\\ 1. Πώς ορίζουμε τη βασική φόρμα μας
\\ Εδώ βάζουμε μέγεθος γραμματων 15, σε πλήρη οθόνη  (μπορεί να βγει και περιθώριο)
\\ Μετά ορίζουμε φόντο το 5 (Ματζέντα), και το εφαρμόζουμε -(καθαρίζουμε την οθόνη)
\\ η δεύτερη παράμετρος λέει ότι η χωριστή οθόνη (αυτή που ολισθαίνει) θα ξεκινάει από τη
\\ πρώτη γραμμή (άρα δεν θα έχουμε χωριστή οθόνη)
\\ Μετά βάζουμε το 14 το κίτρινο.
\\ Τα χρώματα είναι από 0 έως το 15 ως βασικά των Windows
\\ Μπορούμε να δώσουμε RGB με δυο τρόπους:
\\ Με τύπο Html:
\\ το #FFFFFF είναι το άσπρο (πάντα θα πρέπει μετά το # να έχει έξι  νούμερα για να διαβαστεί ως αριθμός html χρώματος)
\\ Με συνάρτηση που γυρνάει το νούμερο (είναι πάντα αρνητικό, ώστε ξεχωρίζει από τα θετικά που είναι ειδικού τύπου)
\\ το Χρώμα(255,255,255) είναι το άσπρο.
\\ Πένα Χρώμα(255,0,0)   \\ βαζουμε το κόκκινο
\\ Πένα #FF0000
\\ Πένα #0000FF  \\ το μπλέ - χρειάζεται τα 0000 στην αρχή.
\\ 2. Κάποια στοιχεία για το πώς αντιγράφουμε την οθόνη και την κρατάμε σε αρχείο ή σε μεταβλητή
\\ 3. Κάποια στοιχεία για την χρήση της εντολής Αναφορά
\\ 4. Την χρήση της Ρώτα() ( και ως Ρώτα$() )
\\ 5. Χρήση μερικών εντολών  νημάτων.
Παράθυρο 15,0
\\ άλλος τρόπος είναι να οριστεί η οθόνη βάσει των χαρακτήρων που θέλουμε με την εντολή Φόρμα
\\ οπότε υπολογίζεται αυτόματα το μέγεθος χαρακτήρων και το διάστιχο, για να έχουμε σε όλο το
\\ παράθυρο αυτό που ζητάμε (εδώ ζητάμε 80 χαρακτήρες επί 40 γραμμές)
\\ κατεβάστε την εντολή φόρμα στην επόμενη γραμμή!
Σημ 1 : Φόρμα 80,40
Οθόνη 5,0
Πένα 14
\\ τα Html χρώματα είναι RGB ενώ στην μνήμη γράφονται σαν BGR, οπότε ισχύουν τα παρακάτω:
Τύπωσε #0000FF=Χρώμα(0,0,255), #0000FF=-(255*256*256), #0000FF=-0χFF0000
Θέση χ.σημεια/5, 3000
Δρομέας ! \\ μετατράπει την θέση του δρομέα γραφικών σε θέση του δρομέα κειμένου
\\ ισχύει και το Θέση ! για μετατροπή αντίστροφη
Κειμ$={   Βάζουμε μερικά κενά στην αρχή για εσοχή! Η Ρώτα() υπάρχει και ως Ρώτα$(). Η δεύτερη γυρνάει το όνομα του πλήκτρου και αν θέλουμε αφήνουμε ένα όρισμα κενό και πάμε στο επόμενο. Αυτή είναι μια παράγραφος, και ακολουθεί άλλη μία.

             - Δουλεύει και σαν MsgBox και σαν InputBox
             
             }
\\ χωρίς αριθμό θεωρεί ότι είναι το 0 - πλήρης στοίχιση
\\ Η Αναφορά γράφει κείμενο με αναδίπλωση  λέξης
\\ μπορούμε να ορίσουμε πλάτος σε σημεία οθόνης ή σε χαρακτήρες
\\ το βρίσκει αυτόματα η εντολή από τον αριθμό, αν είναι μικρός τον θεωρεί ως αριθμό χαρακτήρων
\\ εδώ δίνουμε πλάτος τα 3/5 της οθόνης (της φόρμας εντός του περιθωρίου)
\\ Αν το κείμενο απαιτεί και άλλες γραμμές για να εμφανιστεί και δεν υπάρχουν, τότε περιμένει να πατήσουμε διάστημα ή το αριστερό πλήκτρο του ποντικιού (τυχόν νήματα, ή φόρμας θα συνεχίσουν να τρέχουν)       
Αναφορά Κειμ$, χ.σημεια*3/5
Αναφορά 0, Κειμ$, χ.σημεια*3/5
\\  1 - στοίχιση δεξιά
Αναφορά 1, Κειμ$, χ.σημεια*3/5
\\ 2 - στοίχιση κέντρο
Αναφορά 2, Κειμ$, χ.σημεια*3/5
\\ 3 - στοίχιση αριστερά
Αναφορά 3, Κειμ$, χ.σημεια*3/5

Αν Αληθές Τότε {
      Θέση 0,0
      β$=""
      Ανανέωση
      Αντίγραψε χ.σημεία, υ.σημεία στο β$
} Αλλιώς {
      Αντίγραψε "Οθόνη1"
      \\ τώρα έχουμε το Οθόνη1.bmp στον τρέχοντα κατάλογος Κατ$
      β$=""
      \\ τώρα φορτώνουμε την εικόνα στο β$
      Εικόνα "Οθόνη1" στο β$
}
Θέση χ.σημεία/2, υ.σημεία/2
Εικόνα Β$, χ.σημεία/2
α$="Γιώργος"
Μ=Ρώτα("Το όνομά σου","Αλλαγή ονόματος","ΑΛΛΑΓΗ","ΕΠΙΣΤΡΟΦΗ",β$,α$)
Τύπωσε Μ ' δίνει 0,1 ή 2 '' 0 με Esc, 1με το Αλλαγή, και 2 με το Επιστροφή
Αν Μ=1 Τότε {
      'Στο σωρό έχει αφήσει το αποτέλεσμα
      Διάβασε α$
}

Αν Ρώτα$("Το όνομά σου","Αλλαγή ονόματος","ΑΛΛΑΓΗ","ΕΠΙΣΤΡΟΦΗ",β$,α$)="ΑΛΛΑΓΗ" Τότε {
      Διάβασε α$
}

Αν Ρώτα("Να καθαρίσω την οθόνη", "Ενέργεια", "Καθάρισε","Όχι")=1 Τότε Οθόνη 5,0

Αν Ρώτα("Να καθαρίσω την οθόνη", , "Καθάρισε","Όχι")=1 Τότε {
      Οθόνη : Φόντο 5, 0
      Δρομέας Πλάτος/2,10
      \\ τώρα θα τυπώσουμε το κείμενο από το μέσον της γραμμής και από την 11η γραμμή
      \\ και ορίζουμε πλάτος το ένα τέταρτο της γραμμής
      \\ αφού δεν δίνουμε πρώτο αριθμό σημαίνει ότι θέλουμε πλήρη στοίχιση!
      Αναφορά Κειμ$, Πλάτος/4
      Δρομέας 0,0 \\ Τύπωσε @(0,0),    \\ κάνει το ίδιο πράγμα
}

Κ$={Ένα κείμενο
      η δεύτερη παράγραφος, μπλα μπλα, η δεύτερη παράγραφος, μπλα μπλα,η δεύτερη παράγραφος
      η τρίτη παράγραφος
      η τέταρτη.........
      και άλλη...
      και άλλη...
      }
\\ δοκιμάστε με πάτημα του αριστερού πλήκτρου του ποντικιού να τραβήξετε το κείμενο πάνω ή κάτω
\\ 'Αλλος τρόπος: Στην δεξιά πλευρά εμφανίζεται η μπάρα ολίσθησης  όταν  ο δείκτης του ποντικιού βρίσκεται εκεί.
Μ=0
Μ1=Αληθές
Νήμα {
      Τύπωσε Μ
      Μ++
      Αν Μ=10 Τότε {
            Μετά 2000 {
                  Τύπωσε "Τελείωνε...επιτέλους"
                  Μ1=Ψευδές
                  Ανανέωση
            }
            Νήμα Αυτό Σβήσε
      }
}  Ως Ν Κάθε 50
Αν Ρώτα(Κ$)=1 Τότε Τύπωσε "Οκ"
\\ Η Νήματα Σβήσε βολεύει αν έχουμε νήματα που ορίστηκαν από νήμα
\\ όπως και για "αυτόματα νήματα" όπως αυτό που φτιάχνει η Μετά { }
Νήματα Σβήσε
Αν Μ1 Τότε Τύπωσε "Μπράβο δεν άργησες"




Τρίτη 2 Μαΐου 2017

Αναθεώρηση 17 (Έκδοση 8,7) - Wine Linux

Σε αυτήν την αναθεώρηση έκανα μερικές βελτιώσεις για να τρέχει καλύτερα σε Linux Wine ο διερμηνευτής.


Ένα βασικό πρόβλημα στο Ubuntu Studio με το Wine και το XFCE για τα παράθυρα είναι ότι δεν μετακινεί φόρμες με αλλαγή μεγέθους,όπως θα έπρεπε αν έτρεχε σε Windows. Οι φόρμες χρήστη δεν είχαν πρόβλημα αλλά είχε πρόβλημα η κονσόλα. Και η κονσόλα μπορεί να αλλάξει μέγεθος και να γίνει ένα μικρότερο παράθυρο από πλήρη οθόνη. Μετά από δυο μέρες πειραματισμό βρήκα ότι το πρόβλημα ήταν στην ενημέρωση της φόρμας, για τις αλλαγές μεγεθών. Δεν γίνονταν γρήγορα, και έτσι όταν ζήταγε εσωτερικά τιμές το περιβάλλον του διερμηνευτή έπαιρνε παλαιότερες τιμές! Η λύση που βρήκα ήταν να δίνω εντολή για απόκρυψη και μετά για επανεμφάνιση (ιδιότητα visible). Όταν συμβαίνει αυτό τότε μπορεί να μετακινηθεί η βασική φόρμα μαζί με αλλαγή μεγέθους.
Μπορούμε να ορίσουμε ένα παράθυρο (σε twips οι μονάδες), και να μας το κεντράρει άμεσα (εκεί είχε πρόβλημα, ενώ στην πλήρη οθόνη δεν υπήρχε).
Ακολουθεί ένα πρόγραμμα που δείχνει μερικές εντολές.
Η Παράθυρο έχει παραλλαγές
πχ.
Παράθυρο 10   
Κάνει το τρέχον παράθυρο να δείχνει 10άρια γράμματα (10pt, 1pt=1/72 ίντσας, στην οθόνη λέγεται λογική ίντσα και ισοδυναμούν 1440twips σε μια λογική ίντσα, στον εκτυπωτή μια λογική ίντσα είναι πάντα ίση με τη φυσική ίντσα).
Υπολογίζει βάσει του διάστιχου που έχουμε ορίσει (ορίζεται με την εντολή Διάστιχο 30 ή άλλο νούμερο, ανά 2 pixels, σε twips, αν 1 pixel = 15twips τότε δίνουμε ανά 30) την ανάλυση σε χαρακτήρες μη αναλογικούς (οι θέσεις χαρακτήρων υπολογίζονται να φθάνουν για χαρακτήρες με την τρέχουσα γραμματοσειρά και αν είναι πλάγιοι, και αν είναι φαρδιοί και ή και τα δύο). Κατά μια έννοια δημιουργεί μια εσωτερική κάνναβο οι οποία όχι μόνο δέχεται γράμματα αλλά έχει θέσεις για γραμμές οριζόντιες και κάθετες για να φτιάχνονται περιγράμματα. Η Τύπωσε χρησιμοποιεί την κάνναβο αυτή με στήλες για να εμφανίζει αλφαριθμητικά και αριθμούς και εικόνες. Στις ίδιες στήλες μπορούμε να εμφανίζουμε και αναλογική γραφή (οπότε γράφονται περισσότεροι χαρακτήρες). Επίσης εξ ορισμού η Τύπωσε δεν πειράζει το φόντο (εκτός και αν το ζητήσουμε με εντολές που δέχεται στη λίστα των ορισμάτων που δίνουμε μαζί)
Παράθυρο 10; 
ότι και η προηγούμενη αλλά κεντράρει τη σελίδα.
Παράθυρο 10,0 
Πλήρης οθόνη με δεκάρια γράμματα και αν χρειαστεί βάζει περιθώριο (το περιθώριο είναι ένα επίπεδο πίσω από τη φόρμα που βλέπουμε και μπορούμε να γράψουμε και εκεί, και επιπλέον η οθόνη μας (η φόρμα της κονσόλας) μπορεί να μετακινηθεί μέσα στο περιθώριο.
Παράθυρο 10,12000
Παράθυρο 10,12000, 80000
Δίνουμε πλάτος ή πλάτος και ύψος (όταν πάρει πλάτος τότε υπολογίζει το ύψος από την αναλογία της συσκευής της οθόνης -monitor.
Παράθυρο 10,12000;
Παράθυρο 10, 12000, 8000;
Κεντράρει το παράθυρο

Μια άλλη εντολή η Φόρμα κάνει τρεις δουλειές
Υπολογίζει το μέγεθος από αυτό που ζητάμε:
Φόρμα 60, 40 
Δημιουργεί μια οθόνη (κονσόλα) μέσα στο παράθυρο όπως το έχουμε φτιάξει, αν είναι σε πλήρη οθόνη ή αν είναι σε μικρότερο παράθυρο. Υπολογίζει το διάστιχο, και βρίσκει το μέγεθος των γραμμάτων και δίνει όσο του ζητάμε. Έχει κάποια όρια φυσικά. Το μέγεθος των γραμμάτων το λέμε Τύπος στη Μ2000.
Φόρμα 60
Μπορούμε να δώσουμε μόνο το πλάτος και θα βάλει όσες γραμμές χρειάζεται με το τρέχον διάστιχο .
Οι δυο αυτές παραλλαγές αλλάζουν το περιθώριο, αλλά όχι το παράθυρο. Δηλαδή πάντα η φόρμα θα είναι εντός του παραθύρου

Επειδή η φόρμα δουλεύει βάσει του παραθύρου, μπορούμε να πειράξουμε αυτόματα το παράθυρο:
Φόρμα
Εξαφανίζει το περιθώριο. Έτσι τώρα εκεί που είχαμε 60Χ40 με περιθώριο θα έχουμε χωρίς. (θα δούμε παράδειγμα για τη χρήση του παρακάτω)
Φόρμα;
Αυτή η εντολή βάζει το περιθώριο για να καλύψει όλη την οθόνη και κεντράρει τη κονσόλα στο κέντρο.
Φόρμα 60,4;
Εδώ έχουμε μια φόρμα με 60 χαρακτήρες των 4 γραμμών με το τρέχον διάστιχο (οπότε δεν καλύπτεται όλο το ύψος).
Το παρακάτω εξομοιώνει τη λειτουργία της Φόρμα 60,4; και δείχνει τον υπολογισμό (εδώ όμως κρατάει το διάστιχο που όρισε η Φόρμα 60, 40)

Παράθυρο 8,0
Φορμα 60,40
Φορμα
παράθυρο τυπος, χ.σημεία, υ.σημεία/υψος*4;
Φορμα;
Κίνηση ,0
Περιθώριο 48 {
      Φόντο 1, 5
      Δρομέας 0,Ύψος/2
      Αναφορά 2, "Κεντραρισμένο Κείμενο στο Περιθώριο"
}

Η Κίνηση μετακινεί την κονσόλα εντός, ενώ η Κίνηση.Π μετακινεί το παράθυρο (και ότι έχει μέσα, αλλά όχι τυχόν φόρμες χρήστη, άλλα δηλαδή παράθυρα που μπορεί να φτιάξει)
Τα Κίνηση.Χ , Κίνηση.Υ και Κίνηση.ΧΠ και Κίνηση.ΥΠ δίνουν το σημείο της άνω αριστερή γωνίας, αλλά εδώ τα πρώτα σε σχέση με το παράθυρο και τα δεύτερα με την πλήρη οθόνη (όπου 0,0 είναι η πάνω αριστερή γωνία).

Στις πρώτες εκδόσεις το περιβάλλον της γλώσσας χρησιμοποιούσε την Τύπος (μετά μπήκε η Παράθυρο και μετά η Φόρμα).

Τύπος 14
Κάνει 14άρια τα γράμματα και μειώνει την κονσόλα (πάντα κεντραρισμένη) για να μην υπάρχουν άχρηστα σημεία. Το παράθυρο δεν αλλάζει
Τύπος 14, 10000
Τύπος 14, 10000, 8000
Εδώ οι διαστάσεις είναι ενδεικτικές, γιατί θα μειωθούν για να μην υπάρχουν μη διαθέσιμα σημεία (δεν γράφουμε μισούς χαρακτήρες.
Η εντολή Περιθώριο 22 { } κάνει το Περιθώριο (πίσω από την κονσόλα) να έχει Τύπο 22, αλλά εδώ μπορούν να υπάρχουν σημεία που δεν χρησιμοποιεί η τύπωσε, γιατί δεν πειράζει το μέγεθος του παραθύρου. Μπορούμε να ορίσουμε άλλη γραμματοσειρά με την εντολή Γραμματοσειρά, και γενικά μπορούμε να έχουμε ένα νήμα που να γράφει πίσω, επειδή το περιθώριο είναι ένα επίπεδο με δικό του δρομέα, και μεταβλητές για χρώμα φόντου και πένας.
Η εντολή Οθόνη που καθαρίζει το επίπεδο όπου την εκτελούμε (εξ ορισμού στην κονσόλα, ορίζει με την δεύτερη παράμετρο και το κάτω μέρος που μπορεί να ολισθαίνει. Αυτό το κάνει για το Περιθώριο, το Επίπεδο (χωρίς νούμερο είναι η βασική οθόνη ή κονσόλα) και για άλλα 32 επίπεδα. Τα 32 επίπεδα μπορούν να έχουν γραφικά και κείμενο και σε αυτά λειτουργούν οι εντολές Παράθυρο, Φόρμα, Τύπος με ελάχιστες διαφοροποιήσεις στο αποτέλεσμα.
Εδώ να σημειώσω ότι υπάρχουν δυο επίπεδα ακόμα, ένα που λέγεται Επιφάνεια και σε αυτό δεν γράφουμε και βρίσκεται στο βάθος, και παίρνει ή ένα χρώμα ή ένα αντίγραφο της επιφάνειας εργασίας ή μια εικόνα. Χρησιμοποιείται και σαν "Στοπ" όταν βάζουμε διαφάνεια 100% σε ορισμένα Pixels, γιατί αλλιώς θα κάναμε κλικ στα στοιχεία από πίσω!
Το τελευταίο επίπεδο είναι εκτός οθόνης, είναι η σελίδα του εκτυπωτή. Οι εντολές σχεδίασης, η Τύπωσε, η Αναφορά (που βγάζει φορμαρισμένο κείμενο μιας ή περισσότερων γραμμών, ή ακόμα και μιας ομάδας γραμμών κάνοντας υπολογισμό της αναδίπλωσης λέξεων) λειτουργούν στη σελίδα του εκτυπωτή.

Δοκιμάστε το παρακάτω
Σε Wine με Tahoma που δεν ήταν Unicode γραμματοσειρά χρειάστηκε να δηλώσω με την Χαρακτήρες το 161 (για να φορτωθεί το κατάλληλο αρχείο γραμματοσειράς). Δείχνω μερικούς τρόπους εμφάνισης
Εικόνα από την έξοδο του προγράμματος, σε Ubuntu Studio, με γραμματοσειρά Tahoma Ansi (η Μ2000 χρησιμοποιεί Unicode γραμματοσειρές και Ansi).

Σε κάθε επίπεδο μπορούμε να έχουμε διπλού ύψους/πλάτους γράμματα. Η Αναφορά λειτουργεί εδώ λογαριάζοντας όλο το πλάτος, αλλά μπορεί να λογαριάζει από ένα αριστερό περιθώριο ως ένα πλάτος ή σε χαρακτήρες ή σε σημεία, και να κάνει ανάλογα στοίχιση (έχει και πλήρη στοίχιση). Δείτε επίσης ότι χρησιμοποιεί σωστά το Kerning (πχ στα πλάγια γράμματα φαίνεται περισσότερο, στο Τίτλος στα τλ φαίνεται το ταυ να πέφτει πάνω από το λάμδα.(και ο διορθωτής μπορεί να δουλέψει σωστά με πλάγια γράμματα, το γράφω γιατί και σε αυτόν έχω γράψει το κώδικα)
Δείτε στο κέντρο τρεις γραμμές, η μία δεν αλλάζει το φόντο, η άλλη το έχει αλλάξει με το ματζέντα το χρώμα του φόντου, και η τρίτη έχει φτιάξει ασύμμετρη στήλη (διαφορετικού πάχους από τη πρώτη αριστερά), και έχει βάλει πλαίσιο και φόντο, και κεντραρισμένο κείμενο.
Στο κάτω μέρος φαίνεται η μη αναλογική γραφή που έχει αυτόματη αναδίπλωση ανά χαρακτήρα.
Η τελευταία γραμμή δείχνει την χρήση στηλών με αναλογική γραφή και αλλαγές στο φόντο ανά στήλη (ανά γραμμή).




\\ Πλήρης οθόνη με 14άρια γράμματα, βάζει περιθώριο όσο χρειάζεται
\\ υπολογίζει σε ζυγό νούμερο του χαρακτήρες στη γραμμή
\\ και αν βρει υπόλοιπο το μοιράζει
\\ το διάστοιχο αλλάζει ανά 30 twips (2 pixels στα 15 twips per pixel)
Διάστιχο 60
Παλιά$=Γραμματοσειρά$
Γραμματοσειρά "Tahoma"
\\ η IsWine δίνει -1 αν τρέχει ο διερμηνευτής σε Wine σε Linux
'Αν IsWine Τότε Ελληνικά ' σε Wine μπορεί η γραμματοσειρά Tahoma να μην είναι Unicode
Χαρακτήρες 161
Παράθυρο 14, 18000, 14000;
Οθόνη 5 \\Ματζέντα
Πένα 14 \\ Κίτρινο
Πάχος 4 { \\ πάχος γραμμής σε pixels
      Θέση Χ.Σημεία/2,Υ.Σημεία/2
      Κύκλος Μικρό.Σειράς(Χ.Σημεία, Υ.Σημεία)*.3, 1.2, 1
      Κύκλος Γέμισμα #FF5522, Μικρό.Σειράς(Χ.Σημεία, Υ.Σημεία)*.3*.5,1,#FF5522
}
Αναφορά 2, "Κεντραρισμένος Τίτλος Με Αναλογική Γραφή"
Δρομέας 0,1
Διπλά
Πλάγια 1 \\ ή Πλάγια   για αναστροφή σημαίας
Πένα 15 {
      Αναφορά 2, "Κεντραρισμένος Τίτλος (διπλού ύψους/πλάτους)"
}
Πλάγια 0 \\ ή Πλάγια   για αναστροφή σημαίας
Κανονικά
\\ εκτύπωση με αναλογική γραφή με αλλαγή με τη συνάρτηση $()
Τύπωσε $(4),"Εκτύπωσε σε στήλες",1,2,"οκ",$(0)
\\ εντολή που κόβει το περιθώριο
Φόρμα
\\ αν χρειαστεί κόβει το ύψος (σε Wine)
\\ αυτό γίνεται αν υπάρχει γραμμή εντολών που δεν επιτρέπει
\\  αν δεν βάζαμε το $(0); θα βάζαμε το "";
\\  το ; κολλάει ότι έχει στο προηγούμενο (δεν ακλουθεί τις στήλες), και παράλληλα δεν αλλάζει γραμμή
\\ χωρίς το "" το Ύψος θα κολήσει με το Πλάτος
Πένα 15 {
      Τύπωσε @(0,Ύψος-1),$(4),"οκ", Στήλη, ~(12,7),Πλάτος,~(12,8),Ύψος,$(0);
}
\\ Στην έξοδο του μπλοκ Πένα επανέρχεται το χρώμα πένας σε αυτό που ήταν πριν
\\ Εμφάνιση με μορφή αλφαριθμητικού και ένθεση τιμών
\\ Από Χ.σημεία έχουμε μονάδες σε twips
\\  τα τελευταία μας δίνουν  τα twips ανά pixel σε πλάτος και ύψος (στους εκτυπωτές μπορεί να διαφέρει)
ολο$= Μορφη$("στήλη {0}, οθόνη {1}Χ{2}, φόρμα {3}Χ{4}, ανάλυση {5}Χ{6}, σημείο {7}Χ{8}", Στήλη, Πλάτος, Ύψος, Χ.Σημεία, Υ.σημεία, Ανάλυση.Χ/Πλάτος.Σημείου, Ανάλυση.Υ/Ύψος.Σημείου, Πλάτος.Σημείου, Ύψος.Σημείου)
Τύπωσε @(0,Ύψος-3), ολο$
Δρομέας 0, Ύψος/2-1
Πένα 15 { Αναφορά 1, ολο$ }
\\ απευθείας αναλογική γραφή σε μια στήλη  όλη  η  γραμμή, το $(7) σημαίνει δεξιά στοίχηση σε αναλογική γραφή
\\ οι Τύπωσε Πάνω/Μέρος/Υπό δεν αλλάζουν γραμμή, και μπορούν να αλλάζουν τοπικά το πλάτος στήλης
\\ Η τύπωσε Πάνω ξεκινάει με στήλη όσο το πλάτος, και πρώτα καθαρίζει το φόντο με το χρώμα φόντου
\\ εκτός από μια γραμμή την οποία τη βάζει η Τύπωσε Υπό (και κάνει και αλλαγή γραμμής)
\\ Η Τύπωσε Μέρος και Τύπωσε Υπό κατά τα άλλα μοιάζουν, δεν αλλάζουν άμεσα το φόντο
\\ και έχουν αρχικά το μέγεθος στήλης που δίνει το Στήλη (μόνο διαβάζεται αυτή η μεταβλητή)
Τύπωσε Πάνω $(7), ολο$
\\Τύπωσε Υπό     \\ τυπώνει υπογράμιση σε όλη τη γραμμή
Τύπωσε
\\ αφήνω στήλη 4 μη αναλογικών χαρακτήρων, και θέτω στήλη πλάτος-8, με στοίχιση κέντρο (6)
\\ βάζω χρώμα γραμμάτων φόντου στήλης και περίγραμμα
\\ η στήλη αλλάζει με τη δεύτερη παράμετρο αν είναι αριθμός.
Τύπωσε Πάνω $( ,4),"", $(6 ,Πλάτος-8), ~(3, 7, 15), Κεφ$(ολο$)
\\ αναμονή πλήκτρου
Α$=Κομ$
\\ εντολή που κεντράρει τη φόρμα και βάζει περιθώριο για να καλύψει όλη την οθόνη
\\ και τη σβήνει
Φόρμα ;
Γραμματοσειρά παλιά$
Διάστιχο 0
Φόρμα 60,40 \\ υπολογίζει αυτόματα το μέγεθος χαρακτήρων ανά .25pt (1pt=1/72 inch)
\\ ο Τύπος είναι το μέγεθος χαρακτήρων
\\ Η Χαρακτήρες επιστρέφει την Ansi σελίδα χαρακτήρων
Τύπωσε Χαρακτήρες, Διάστιχο, Τύπος
Τύπωσε Γραμματοσειρά$
Επίλεξε.Γραμματοσειρά
Αν Αριθμός>0 Τότε {
Διάβασε όνομα$, τυποςγρ, χαρ, πλαγιαστά, έντονα
Τύπωσε όνομα$, τυποςγρ, χαρ, πλαγιαστά, έντονα
}




Απλός το αναφέρω και θα το δούμε κάποια στιγμή. Πριν φτιάξω τις φόρμες χρήστη (GUI) είχα (και παραμένουν) τους στόχους σε κάθε επίπεδο, όπου μπορούσαν έπειτα από Σάρωση (μια εντολή δηλαδή) να διαβαστεί αν έχουμε πατημένο το δείκτη του ποντικού και να εκτελέσουν ένα γενικό τμήμα (πριν κατανοήσω πως φτιάχνουμε τα γεγονότα, και έτσι έφτιαξα τις φόρμες χρήστη, με στοιχεία ελέγχου). Μπορεί λοιπόν με τη βασική φόρμα να φτιάξει διάφορες οθόνες και να παρουσιάζει εικόνες, ήχους, κινούμενες εικόνες (τα 32 επίπεδα δουλεύουν και ως sprites, με δυνατότητα μεγέθυνσης και περιστροφής), βίντεο και html σελίδες, και να έχει στόχους για να αλλάζει οθόνες ή να κάνει επιλογές γενικότερα. Στόχος ήταν να έχει κανείς την δυνατότητα να στήσει multimedia εφαρμογές. Αν βάλουμε ότι η γλώσσα φτιάχνει και συνδέεται με βάσεις δεδομένων, παίζει μουσική (από wav αρχεία), μιλάει με τη χρήση του συνθεσάιζερ φωνής (όχι σε Wine), παίζει μουσική με νότες, με νήμα, κατά την εκτέλεση άλλων εντολών δηλαδή (στο Wine δεν βρήκα πως να το κάνω να ακούγεται, κάτι λείπει, μάλλον τα sound fonts αλλά δεν έχω γνώση επί του θέματος, ακόμα), τότε λοιπόν αυξάνονται κατά πολύ οι επιλογές και οι χρήσεις της γλώσσας.
(Οι εντολές για ήχο είναι η Μουσική, Φωνή, Παίξε,  Λόγος, Τόνος, Περιθώριο Μουσική όπου με αλφαριθμητικό παίζει αρχείο μουσικής στο περιθώριο)

Ωραίο παράδειγμα (τρέχει σε Wine) παίζει μουσική στο περιθώριο, παίζουμε πάνω σε αυτήν ένα δεύτερο κομμάτι, και στο τέλος παίζουμε μουσική που σταματάει τις εντολές αλλά όχι το νήμα Κ. Χρειάζεται ένα αρχείο ήχου (το tada.wav από windows)








Περιθώριο Μουσική "tada.wav"
Για ι=1 Έως 200 {
      Τύπωσε ι,
      Ζ=Διάρκεια
      Αν Ζ<>0 Τότε Τύπωσε Μουσική, Στρογγ((Ζ-Μουσική.Μετρητής)/Ζ*100,2), Ζ,
      Τύπωσε
      Αν ι=30 Τότε Μουσική "tada.wav"      
}
Περιθώριο Μουσική \\ κόβει άμεσα τη Μουσική περιθωρίου
\\ Μουσική \\κόβει τη Μουσική
Ενώ Μουσική {
ι++
Τύπωσε ι,
      Ζ=Διάρκεια
      Αν Ζ<>0 Τότε Τύπωσε Μουσική, Στρογγ((Ζ-Μουσική.Μετρητής)/Ζ*100,2), Ζ,
      Τύπωσε
}
Τύπωσε ι, Μουσική
Νήμα {
Τύπωσε ι
ι++
Ανανέωση
} Ως Κ Κάθε 30
\\ το παρακάτω...δεν σταματάει το νήμα Κ
Μουσική "tada.wav";  \\ παίζει Μουσική και μετά συνεχίζει στην επόμενη εντολή
Τύπωσε "οκ"