Σάββατο 9 Ιουνίου 2018

Χρήση Υπερκλάσης και Γεγονότων για παραγωγή ομάδων με σειριακό αριθμό!

Και αυτό το παράδειγμα έχει γραφτεί στο νέο μικρό εγχειρίδιο που ετοιμάζω.
Η κλάση ΝέαΟμαδα δημιουργεί μια κλάση που κληρονομεί την υπερκλάση ένα. Στη Μ2000 μια ομάδα μπορεί να έχει μια υπερκλάση, και μια υπερκλάση δεν μπορεί να έχει άλλη. Μπορούμε όμως να δημιουργήσουμε ομάδες από άλλες ομάδες, έτσι κατά μια έννοια η κληρονομικότητα γίνεται λόγω "Συγχώνευσης" ομάδων. Η διαφορά με την υπερκλάση είναι ότι αφήνει ένα σύνδεσμο σε αυτή,  ένα δείκτη, και η Για Υπερκλάση {} καλεί στοιχεία της υπερκλάσης, και έτσι όσες ομάδες έχουν συνδεθεί με την υπερκλάση έχουν πρόσβαση σε κοινές ιδιότητες. Μια υπερκλάση μπορεί να έχει μοανδικά στοιχεία που δεν τα δίνει στις υποκλάσεος αλλά αυτές μπορούν να τα προσεγγίσουν. Εδώ η μεταβλητή "αρχικός" είναι μοναδική και κρατάει τον επόμενο αριθμό σειράς.
Καλώντας την κλάση δέκα φορές με πέρασμα με τιμή της Δύο, ο δείκτης της υπερκλάσης αντιγράφεται, όπως επίσης και η λίστα συνδεδεμένων γεγονότων. Έτσι δημουργούμε στο τελικό προιόν της συνάρτησης κλάσης, μια ομάδα με υπερκλάση και με λίστα γεγονότων (εδώ έχουμε ένα μόνο γεγονός το "αριθμός_σειράς".
Από το πίνακα Α(10) με δέκα στοιχεία από 0 έως 9, δημιουργούμε δυο άλλες ομάδες ως αποτέλεσμα της συνάρτησης Παραγωγή(). Αυτή η συνάρτηση αρχικά σώνει τον αριθμό σειράς, μετά παράγει έναν άλλο και τον γράφει έτσι ώστε να βγει ένα αντίγραφο που θα επιστραφεί από τη συνάρτηση με τον νέο αριθμό σειράς και μετά επαναφέρουμε τον παλιό αριθμό σειράς. Κάθε φορά χειριζόμαστε την ιδιωτική μεταβλητή, πίσω από την ιδιότητα ΣειριακόςΑριθμός, η οποία είναι μόνο για ανάγνωση (αλλά παίρνει την τιμή από την ιδιωτική [ΣειριακόςΑριθμός].
Στο τέλος από το τελευταίο παραγώμενο κάνουμε επίσης μια παραγωγή, το ΜΜ3. Και αυτό θα πάρει το κανονικό αριθμό σειράς (εδώ 13). Σε κάθε περίπτωση, το γεγονός της παραγωγής του επόμενου αριθμού σειράς θα εξυπηρετηθεί και θα φανεί σαν ενημέρωση στην κονσόλα με την Τύπωσε.

Η συναρτηση Δύο_αριθμός_σειράς είναι μια "ψεύτικη" συνάρτηση. Όταν κληθεί από το σύστημα των γεγονότων, θα αλλαχθεί το όνομά της με το όνομα του τμήματος όπου βρίσκεται (πχ αν το πρόγραμμα βρίσκεται στο Α θα μπει ως όνομα το Α) έτσι κάθε μεταβλητή του Α θα είναι θεατή στη κλήση αυτή.
Με τον ίδιο τρόπο γίνονται και οι κλήσεις γεγονότων στο σύστημα των παραθύρων της Μ2000.



\\ Θέλουμε η υπερκλάση να κρατάει τον μοναδικό επόμενο αριθμό σειράς
Υπερκλάση Ένα {
      Γεγονός "αριθμός_σειράς"
      Μοναδικό:
            αρχικός=1&
      Δημοσιο:
            Συνάρτηση Επόμενος {
                  Για Υπερκλάση {
                        =.αρχικός
                        Κάλεσε Γεγονός "αριθμός_σειράς", .αρχικός
                        .αρχικός++
                  }
            }      
}
\\ Θέλουμε μια κλάση να παίρνει την υπερκλάση και να δημιουργεί
\\ μια νέα ομάδα, με κατάλληλο αριθμό σειράς
\\ και με δυνατότητα παραγωγής αντιγράφου με τον επόμενο αριθμό σειράς
Κλάση ΝεαΟμάδα {
      Ιδιότητα ΣειριακόςΑριθμός { Αξία }=0
      Συνάρτηση Παραγωγή {
            Παλιός=.[ΣειριακόςΑριθμός]
            .[ΣειριακόςΑριθμός]<=.Επόμενος()
            =Αυτό
            .[ΣειριακόςΑριθμός]<=Παλιός
      }
Κλάση:
      Τμήμα ΝεαΟμάδα (Ομαδα1) {
              Αυτό=Ομάδα1
             .[ΣειριακόςΑριθμός]<=Ομάδα1.Επόμενος()
      }
}
\\ Παράλληλα θέλουμε όταν παράγεται ένας αριθμός σειράς να φαίνεται
\\ μέσα από την κλήση ενός γεγονότος.
\\ Η υπερκλάση δεν μπορεί να συνδεθεί άμεσα με εξυπηρετητές γεγονότων
\\ μπορεί όμως μια ομάδα να πάρει την υπερκλάση και να συνδεθεί με εξυπηρέτηση γεγονότων
Ομάδα ΜεΓεγονότα Δύο=Ένα
Συνάρτηση Δύο_αριθμός_σειράς {
      Τύπωσε "Νέος αριθμός σειράς", Αριθμός
}
\\ Ο τελεστής << κάνει την Κλάση ΝέαΟμάδα() να εκτελείται για κάθε στοιχείο του Α()
\\ Έτσι παράγεται για κάθε στοιχείο ένας νέος σειριακός αριθμός και ένα γεγονός μας το λέει!
Πίνακας Α(10)<<ΝεαΟμαδα(Δύο)
\\ Μπορούμε να διαβάσουμε το σειριακό αριθμό με τη χρήση της ιδιότητας για ανάγνωση μόνο
Για ι=0 έως 9 {
      Τύπωσε Α(ι).ΣειριακόςΑριθμός
}
\\ Κάθε στοιχείο μπορεί να παράγει ένα ίδιο με τον επόμενο αριθμό σειράς!
\\ τώρα παράγουμε ένα αντίγραφο με νέο αριθμό σειράς το 11
ΜΜ=Α(3).Παραγωγή()
Τύπωσε ΜΜ.ΣειριακόςΑριθμός ' δίνει 11
ΜΜ2=Α(6).Παραγωγή()
Τύπωσε ΜΜ2.ΣειριακόςΑριθμός ' δίνει 12
\\ Τώρα θα παράγουμε από το ΜΜ2 που έχει παραχθεί από το Α(6)
ΜΜ3=ΜΜ.Παραγωγή()
Τύπωσε ΜΜ3.ΣειριακόςΑριθμός ' δίνει 13

Χρήση γεγονότων σε ομάδες με εξωτερικές συναρτήσεις εξυπηρέτησης γεγονότων

Σε αυτό το παράδειγμα (υπάρχει παρόμοιο στα αγγλικά εδώ με την διαφορά ότι όταν εμφανίστηκαν αυτού του τύπου τα γεγονότα, δεν υπήρχαν δείκτες σε ομάδες) θα δούμε τα "ελαφριά γεγονότα". Τώρα επειδή υπάρχουν δείκτες θα δούμε ότι και οι δείκτες σε ομάδες μπορούν να καλέσουν μεθόδους (τμήματα) σε ομάδες και αυτές να καλέσουν τις συνδεδεμένες συναρτήσεις (αν υπάρχουν). Η κλήση σε γεγονότα μπορεί να γίνει και με πέρασμα με αναφορά, όπως η &Μ. Επίσης και έχει σημασία εδώ, οι συναρτήσεις εξυπηρέτησης γεγονότων δεν ανήκουν σε ένα αντικείμενο γεγονός αλλά είναι "Δεμένες" με το τμήμα όπου φτιάξαμε την αρχική "Επώνυμη" ομάδα άλφα. και από αυτήν συνδέσαμε τα γεγονότα "α" και "β" στις συναρτήσεις Άλφα_α και Άλφα_β. (παρόμοιο τρόπο σύνδεσης συναρτήσεων εξυπηρέτησης έχουμε και στις φόρμες χρήστη GUI, και τα στοιχεία ελέγχου σε αυτές).
Κάνουμε δοκιμές σε αντίγραφα της άλφα σε έναν πίνακα, τον οποίο τον περνάμε με αντιγραφή σε ένα άλλο τμήμα. Επίσης φτιάχνουμε ένα δείκτη σε ένα στοιχείο του πίνακα και μετά φτιάχνουμε ένα νέο πίνακα όπου στο στοιχείο 1 βάζουμε ένα δείκτη από στοιχείο του πρώτου πίνακα, Το δεύτερο πίνακα τον περνάμε με αναφορά σε ένα άλλο τμήμα και εκεί καλούμε δυο φορές το ΈλεγχοςΑ το οποίο καλεί το γεγονός Άλφα_α (που βρίσκεται σε άλλο τμήμα). Αυτό το γεγονός εκτελείται σε μια συνάρτηση που "πιστεύει" ότι είναι μέρος του τμήματος, και όχι χωριστή συνάρτηση, και έτσι βλέπει και τροποποιεί την Μ, μια μεταβλητή με ίδιο όνομα όπως η Μ στο τμήμα ΈλεγχοςΑ, αλλά διαφορετική. Η Μ στην ΈλεγχοςΑ είναι τοπική, που σημαίνει ότι στο πέρας εκτέλεσης του τμήματος θα χαθεί. Δείτε όμως ότι κατά την κλήση του γεγονότος "α" δίνουμε την τιμή του Χ (έχει μια τελεία στην αρχή) και αυτό είναι μέλος της ομάδας, και αμέσως μετά αυξάνουμε κατά ένα την τιμή του (και αυτό μένει στην ομάδα, γιατί η Χ δεν είναι τοπική αλλά μέλος της ομάδας, δηλαδή κρατάει μια "κατάσταση" όπως λέμε).
Κάθε φορά που καλούμε το γεγονός "α" από οποιοδήποτε αντίγραφο της Άλφα θα αυξάνει το Μ, στο τμήμα που βρίσκεται η αρχική ομάδα Άλφα.


Άδειασε ' αδειάζουμε το σωρό για να δείξουμε παρακάτω ότι δεν "γεμίζει"
\\ η χρήση γεγονότων χρειάζεται όταν το αντικείμενο δεν ξέρει,
\\ με τι συνδέεται το γεγονός, αλλά ότι πρέπει να το καλέσει!
\\ ακόμα και αν δεν είναι συνδεδεμένο (δεν βγαίνει λάθος)
\\ στην ουσία προγραμματίζουμε το αντικείμενο, χωρίς να πειράζουμε το κώδικά του!
Ομάδα ΜεΓεγονότα Άλφα {
      Γεγονότα "α", "β"
      Χ=10
      Τμήμα ΈλεγχοςΑ {
            Κάνε Μ ως Μακρύς
            Κάλεσε Γεγονός "α", ,
            ++
            \\ ο σωρός είναι 0 και το Μ είναι 101, στην πρώτη κλήση
            Τύπωσε Μέγεθος.Σωρού, Μ
       }
       Τμήμα ΈλεγχοςΒ(τι$) {
            Κάλεσε Γεγονός "β", τι$
      }
}
Μ=100
α_τιμή=500
β_τιμή=4000

\\ αν αλλάξουμε τα ονόματα των Αλφα_α και Αλφα_β
\\ με τα Αλφα_α1 και Αλφα_β1
\\ το πρόγραμμα θα τρέξει χωρίς να κληθούν οι συναρτήσεις
\\ και χωρίς να βγει λάθος
\\ τα γεγονότα δηλαδή καλούνται ανεξάρτητα αν έχουν συνάρτηση εξυπηρέτησης.
\\ στην Άλφα_α βάζουμε το Νέο για να δηλώσουμε ότι η αναφορά θα γίνει, ακόμα και αν υπάρχει ήδη μια α, την οποία θα σκιάσουμε πρόσκαιρα.
Συνάρτηση Άλφα_α(Νέο &α_τιμή,β_τιμή) {
      \\ η συνάρτηση είναι όπως οι συναρτήσεις γεγονότων για φόρμες
      \\ έχουν ίδιο όνομα κατά την εκτέλεση με το τμήμα που ανήκουν
      \\ έτσι η Μ είναι φανερή και μπορεί να αλλάξει
      Μ++
      α_τιμή=Μ
      Τύπωσε "ok", α_τιμή, β_τιμή, Μ
      Βάλε 500 ' η τιμή θα χαθεί γιατί ο σωρός τιμών είναι προσωρινός και στην επιστροφή διαγράφεται
}
Συνάρτηση Άλφα_β(α_τιμή$) {
      Τύπωσε "Από Γεγονός:"; α_τιμή$
}
Άλφα.ΈλεγχοςΑ
Σωρός ' απλά αφήνει μια γραμμή γιατί δεν έχει τίποτα ο σωρός
\\ φτιάχνουμε ένα πίνακα με δέκα ομάδες όπως η άλφα
Τύπωσε Αλφα.χ ' δίνει 11
Πίνακας πινακ(10)=Αλφα
Τμήμα Ζ_τμήμα (M()){
      Για ι=0 έως 9 {
                  Για M(ι) {
                        \\ καλούμε σε κάθε στοιχείο του Μ την έλεγχοςΑ
                        \\ η οποία θα καλέσει το γεγονός
                        .ΈλεγχοςΑ
                  }
      }
      M(5).ΈλεγχοςΒ "Αυτό είναι το Μ(5)"
}
\\ εδώ ο πίνακας πινακ() πέρασε με αντιγραφή
Ζ_τμήμα πινακ()
Βήτα=πινακ(3)
Βήτα.ΈλεγχοςΒ "Γεια Χαρά!"
Τύπωσε α_τιμή, β_τιμή ' δεν έχουν αλλάξει!
Δ1->Βήτα
Δ1=>ΈλέγχοςΒ "Δ1"
Πίνακας πιν1(5)
πιν1(1)->πινακ(1)
πιν1(1)=>ΈλεγχοςΒ "πιν(1)"
Τμήμα κάτι_αλλο (&π()) {
      π(1).ΈλεγχοςΑ ' το π(1).χ γίνεται 12
      π(1).ΈλεγχοςΑ ' το π(1).χ γίνεται 13
}
κάτι_αλλο &πιν1()
\\ το παρακάτω δίνει 13, γιατί;
\\ επειδή το π(1) είναι δείκτης του πινακ(1)
\\ ο οποίος ξεκίνησε με αντίγραφα του Αλφα που είχε το Αλφα.Χ = 11
Τύπωσε πινακ(1).Χ

Αναθεώρηση 10 (έκδοση 9.3) και παράδειγμα CSV+ Excel

Έχει ανέβει η αναθεώρηση 10 της έκδοσης 9.3. Παράλληλα γίνεται ανανέωση στο μικρό εγχειρίδιο της Μ2000 (στα ελληνικά). Παρακάτω είναι ανανεωμένο το παράδειγμα που ετοιμάζει ένα αρχείο το στέλνει στο Excel. Εκεί το σώνουμε και κλείνουμε το Excel και αυτόματα το διαβάζει το πρόγραμμα. Δουλεύει για οποιοδήποτε χαρακτήρα διαχωρισμού δεκαδικών, επειδή διαβάζει άμεσα το τρέχον και προσαρμόζει την εξαγωγή (και την εισαγωγή) στο αρχείο.

Επίσης εδώ χρησιμοποιούμε την παραλλαγή όπου τα αλφαριθμητικά δεν γράφονται στο αρχείο CSV με εισαγωγικά.


\\ Με το πρόγραμμα αυτό θα φτιάξουμε ένα CSV αρχείο
\\ το οποίο θα το διαβάζει το excel

Κανε ακέραιο κ \\ η τιμή ορίζεται από την Ανοιξε

\\ το 0xE δίνει το σύμβολο για τα δεκαδικά - μπορεί να είναι το κόμμα ή η τελεία.
Τοπικό 0 ' για να διαβάσουμε το τρέχον τοπικο$(0xE) και όχι κάποιο ειδικά
Κάνε ΑλλαξεΤελεία$(α$)=αλλαγη$(".",τοπικο$(0xE),α$)
Δες οκ {
Άνοιξε "αλφα.csv" για ευρεία εξαγωγή ως κ
}
Αν όχι οκ Τότε Λάθος "Δεν μπορώ να ανοίξω το αρχείο αλφα.csv"
      Τύπωσε #κ, χαρκωδ$(0xFEFF); \\ λέγεται BOM και μαρκάρει το κείμενο ως UTF-16LE
      \\ το ; κάνει την τύπωσε να μην βάζει αλλαγή γραμμής
      \\ οι αριθμοί στο κώδικα γράφονται πάντα με τελεία για δεκαδικό
      \\ στην εμφάνιση στην Τύπωσε βγαίνουν βάσει του τοπικού
      Γράψε με χαρ$(9), τοπικο$(0xE) ,, αληθες
      Γράψε #κ, "Τιμή Α", "Τιμή Β","Αποτέλεσμα Κ"
      Γράψε #κ, 12.24, 213.23, 213.23+12.24
      Γράψε #κ, 15.24, 215.23, 215.23+15.24
      Γράψε #κ, ΑλλαξεΤελεία$("=A2+A3*2.5"), ΑλλαξεΤελεία$("=B2+B3*2.5"), ΑλλαξεΤελεία$("=C2+C3*2.5")
Κλείσε #κ
Γράψε με "",""  \\ κάνουμε επιστροφή στις τιμές κόμμα και τελεία
Σύστημα "Excel.exe ", παράθεση$(κατ$+"αλφα.csv")
\\ δίνουμε ένα χρόνο 3 δευτερολέπτων για να ανοίξει το αρχείο το Excel
Αναμονή 3000
Έγγραφο Excel$
{
      Δες οκ {
            \\ αν είναι ανοιχτό με το Excel είναι για αποκλειστική χρήση
            \\ οπότε βγαίνει λάθος η συμπλήρωση (append)
            Άνοιξε "αλφα.csv" για συμπλήρωση ως κ
            Κλείσε #κ
            Φόρτωσε.Έγγραφο Excel$, "αλφα.csv"
      }
      αν λάθος ή οχι οκ τότε αναμονή 100 : κυκλικα
}
\\ μας εμφανίζει τα στοιχεία που φόρτωσε το έγγραφο
\\ στο έγγραφο το BOM έχει αφαιρεθεί!
Αναφορά Excel$
\\ Όπως ορίζουμε τρόπο για την Γράψε, έτσι ορίζουμε και για την Εισαγωγή
\\ το πρώτο ορίζει τον χαρακτήρα που διαχωρίζει τα στοιχεία στην γραμμή
\\ το δεύτερο ορίζει τον χαρακτήρα για το διαχωριστικό δεκαδικών
\\ η τρίτη προαιρετική παράμετρος με αληθές δηλώνει ότι ειδικοί χαρακτήρες θα έχουν escape κωδικούς
\\ η τέταρτη προαιρετική παράμετρος δηλώνει ότι τα αλφαριθμητικά δεν θα έχουν εισαγωγικά
Τοπικό 0 ' είναι ήδη 0 αλλά το βάζουμε για να φανεί ότι είναι απαραίτητο
Εισαγωγή με χαρ$(9), τοπικο$(0xE) ,, Αληθές
Άνοιξε "αλφα.csv" για ευρεία εισαγωγή ως κ
      \\ μπορούμε να μεταθέσουμε τον δρομέα, από το 1 που είναι η αρχή στο 3
      \\ και έτσι να αφήσουμε το BOM έξω
      Μετάθεση #κ, 3
      \\ τώρα διαβάζουμε τις επικεφαλίδες
      Εισαγωγή #κ, τ1$, τ2$, τ3$
      Τύπωσε τ1$, τ2$, τ3$
      Για ι=1 έως 2 {
            Εισαγωγή #κ, τ1, τ2, τ3
            Τύπωσε τ1, τ2, τ3
      }   
      \\ ίσως να μην έχει γίνει καταχώρηση οπότε θα πάρουμε αλφαριθμητικά
      Εισαγωγή #κ, τ1$, τ2$, τ3$
      Αν Θέση(τ1$,"=")=0 τότε {
            τ1=Τιμή(τ1$)
            τ2=Τιμή(τ2$)
            τ3=Τιμή(τ3$)
            Τύπωσε τ1, τ2, τ3
      } Αλλιώς {
            Τύπωσε τ1$, τ2$, τ3$
      }
Κλείσε #κ

Πέμπτη 7 Ιουνίου 2018

Revision 9 (Version 9.3) plus an example of OOP

In revsion 9, mostly work done for editor. There is a plan for next revision to include the new glist user control from TexViewer, for handling input for Chinese ideograms.



About this example.
This is the OOP program. M2000 is not full OOP, because we can make programs with no use of objects.  A group is the object in M2000. A group may have members, any kind of memory containers, like a variable or an array, and methods as Modules and Functions. Also a Group may have other groups inside, and properties as groups which set or get values from them. We can define operators too. The different in M2000 is that all groups, are one kind. We can use pointers to groups, and method dispatch" is dynamic always.
We can use encapsulation by using private members. By default a group exist without a pointer, under a name or in a position in an indexed container, like an array, or in a position in a stack, or in under a key in a Inventory container (something like a vector). In version 9, of M2000 we can use pointers, so there is a way to keep a group only by pointer. Any group may have a superclass. But a superclass must be prepared as a superclass, so a group can't act as superclass. So we have one level of hierarchy only. A superclass is linked by pointer, and only a subclass has access to unique or with same name superclass members. There is another way to make an accumulative group, which we say that a base group can merge members from another group(s). There is no copy of group. and assign a group to another group (not pointers) we get is a merge function. Also we can change any module/function/operator later (except we defined them as final). Also there is a way to make temporary modules (not explain here) using a reference to group and adding to that reference members (which original group never get).
A named group can export reference to it, and this reference is not a pointer to it. References can't changed to point something else. Pointers may changed to point to another group or to null. References used to pass a by reference a group. Because in m2000 we can pass by reference functions, and group functions, we can call a method of Group B from Group A, passing a reference to group B or passing a reference of a function of Group B which call B own functions. Also there are special events for groups, so we can set an event to perform a call, which means that actual object never knows what call, but is the work of event setup to perform the link action. Here we see something more simple from that.

I get the idea from a Java book, the complete reference ninth edition Oracle Press. Because in java we need to define types before compiling, we use an interface or a superclass as a pointer to make it work for a number of different objects, using the strong element of polymorphism. Such a thing isn't a problem for M2000 because, we don't have compiler. all code are interpreted and there is no need to check types, if we use a function that doesn't exist we get an error. The good in Java is that we get the error before compiling. So how bad is to know in advance, before running a program that the program is ok, by reading it? In any case there are faults, and that faults maybe a compiler can't find, and we need to test run the program, maybe many times. M2000 can be used for prototyping, means to make programs from ideas, without optimizations by any compiler. We need to get exactly what we want to get, and anything else is a fault.


\\ make console 60 chars by 40 lines
Form  60, 40
Module Global PressSpaceBar {
      Print "Press SpaceBar"
      \\ using Wait we pass control to os
      \\ this happen if we use standard speed (Fast) or slow speed
      \\ based on a timer. but in extreme speed (Set Fast !) this not hold
      \\ we have to use Wait 0 or something
      While Inkey$<>" " {Wait 0}
}
Module Inside {
      \\ this is inside Inside and we have to call it to create and use anything defined here
      \\ A superclass is group with not members immediate exposed
      \\ to ger members we have to copy it to a name
      \\ a copy of a superclass make two things. One is a copy of all members to new name
      \\ and second a pointer to superclass, so we can get superclass same members, or unique members
      \\ through subclass, using For SuperClass Blcok. But here we don't use it
      \\ We only demonstrate  how "virtual function" works
      \\ for this example we can alter SuperClass with Group
      \\ the output will be the same
      SuperClass Figure {
      Private:
            dim1, dim2
      Public:
            Group GetDim1 {
                  Value {
                      link parent dim1 to dim1
                      =dim1
                  }
            }
            Group GetDim2 {
                  Value {
                      link parent dim2 to dim2
                      =dim2
                  }
            }
            \\ a property is a group always public
            \\ and we can make a Value part, a Set part, or each of these parts
            \\ here we place Value without block, and we set first Value to zero
            \\ so this is a read only property
            \\ there is a [AreaProp] private member in Figure which we can alter it
            Property AreaProp {
                  Value
            }=0
            Function Area {
                  Print "Area for Figure is undefinded"
                 =.AreaProp
            }
            \\ each time we place new dim1, dim2 values, we erase AreaProp
            \\ see <= we use to asign value in a member - otherwise we make a local variable.
            \\ <= not used for arrays (they defined using Dim, or Local or Global)
            Module Figure(.dim1, .dim2) { .[AreaProp]<=0 }
      }
      \\ A class is a function which return a group
      \\ also it is ag lobal functions - and exist until this module end
      \\ but his not hold if class defined in a group.
      \\ here constructor (same name as class name), get three things
      \\ a group, a
      Class Rectangle {
      \\ after class:  all modules/functions can be used only inside this "class" function
      \\ so Rectangle used once only
      \\ we can use module Rectangle(sup, a, b) without types
      \\ or Module Rectangle { Read sup, a, b  : ...code here }
      class:
            module Rectangle(sup as group, a as double, b as double) {
                  \\ sup is a group, so we can use figure to construct it
                  \\ figure is not a constructor, because can't change "this" but values of members only
                  sup.figure a, b
                  \\ we can add some properties, or we can change any property/function/module
                  \\ using additional group definition
                  group sup {
                        Property AreaProp {
                               Value {
                                    if Value=0 then {
                                    \\ compute once, and saveit to [AreaProp] in parent private member
                                    \\ a property is a group inside a group, and can't read parent members
                                    \\ we have to link (to make references)
                                           Link parent dim1, dim2, [AreaProp] to dim1, dim2, Ap
                                                Value=dim1*dim2
                                                AP=Value
                                    }
                              }
                        }
                        Function Area {
                              Print "Inside Area For Rectangle"
                            \\  =.dim1*.dim2
                              =.AreaProp
                        }
                  }
                  \\ so now we can place a copy of final sup to This object
                  this=sup
            }
      }
      Class Triangle {
            class:
            module Triangle(sup, a, b) {
                  sup.figure a, b
                  group sup {
                        Property AreaProp {
                               Value {
                                    if Value=0 then {
                                    \\ compute once, and save it to [AreaProp] in parent private member
                                          Link parent dim1, dim2, [AreaProp] to dim1, dim2, Ap
                                          Value=dim1*dim2/2
                                        Ap=Value
                                     }                                         
                              }
                        }
                        Function Area {
                              Print "Inside Area For Triangle"
                              =.AreaProp
                        }
                  }
                  this=sup
            }
      }
      Fig1=Figure
      Fig1.Figure 10, 10
      M=Fig1.Area()
      Print M
      Rect1=Rectangle(Figure, 9,5)
      M=Rect1.Area()
      Print M
      Triag1=Triangle(Figure, 10,8)
      M=Triag1.Area()
      Print M
      \\ NOW WE USE A POINTER TO OBJECT
      GroupRef->Fig1
      M=GroupRef=>Area()
      Print M
      GroupRef->Rect1
      M=GroupRef=>Area()
      Print M
      GroupRef->Triag1
      M=GroupRef=>Area()
      Print M
      Dim A(12)
      \\ FIRST WE USE COPIES OF OBJECTS IN ARRAY
      \\ EACH COPY IS A NAMELESS OBJECT. EXIST ONLY AS AN ITEM IN AN ARRAY.
      \\ ALL MEMBERS ARE HIDDEN FROM SYSTEM, WHEN NOT IN USED
      \\ EACH TIME WE USE A NAMELESS OBJECT  IT GET A HIDDEN NAME, AND OPEN FOR USE
      A(0)=Fig1
      A(1)=Triag1
      A(2)=Rect1
      For k=0 to 2 {
            M=A(k).Area()
            Print M
      }
      \\ WE CAN OPEN USING FOR
      For A(1) {
            Print .getdim1, .getdim2
            \\ MM is a temporary group
            \\ and get a copy of A(1) (which is a copy of Triag1)
            MM=This
            Group MM {
                  Module PrintDim1Dim2 {
                        Print "Read from a copy of group"
                        Print .Dim1, .Dim2
                  }
            }
            MM.PrintDim1Dim2
            \\ Because we know that dim1 and dim2 are the two first members
            \\ and the fifth is [AreaProp], we can get  references to them
            \\ and also these are for temporary use, in this block
            \\ Read statement have some variants...
            Read From MM, &d1, &d2,,,&Area
            \\ this is the only way to get a referenve from private members, outside of an object
            Print d1, d2, Area
            d1*=2
            d2*=3
            Area=0 ' erase it, so we can copmute it again
            Print d1, d2, Area
            Print MM.AreaProp
      }
      PressSpaceBar
      \\ we can use nested for, or multiple object in any for
      \\ but there is a rule of dots
      \\ in each execution object each added object in For { } add a dot
      \\ so for A(0) we have one dot, fot A(1) two and for A(3) three
      For A(0) {
      \\ also first object can be This (if code run outside of a group member module or function, or a child module or function everywhere)
            For A(1), A(2) {
                  Print "Figure:", .getdim1, .getdim2
                  Print "Triangle", ..getdim1, ..getdim2 ' look double dot before name
                  Print "Rectangle", ...getdim1, ...getdim2 ' look triple dot before name
            }
      }
      PressSpaceBar
      \\ NOW WE USE POINTERS TO OBJECTS
      A(3)->Fig1
      A(4)->Triag1
      A(5)->Rect1
      For k=3 to 5 {
            M=A(k)=>Area()
            Print M
      }
      PressSpaceBar
      \\ NO WE USE POINTERS TO UNAMED OBJECTS
      A(6)->A(0)
      A(7)->A(1)
      A(8)->A(2)
      For k=6 to 8 {
            M=A(k)=>Area()
            Print M
      }
      PressSpaceBar
      \\ NOW WE USE POINTERS TO POINTERS TO NAMED OBJECTS
      \\ NAME OBJECTS ARE "STATIC" MEANS THAT EXIST UNTIL NAMES GET OUT OF SCOPE
      \\ AND THAT HAPPEN AT THE END OF EXECUTION OF A MODULE (WHICH IS THE END OF AN EXECUTION OBJECT)
      \\ OR IN A FOR OBJECT(S) BLOCK WHICH ALSO DESTROY ANY NEW NAME (BUT EXECUTION OBJECT NOT END)
      A(9)->A(3)
      A(10)->A(4)
      A(11)->A(5)
      \\ THIS IS NOT A FOR OBJECT BLOCK BUT A FOR LOOP BLOCK
      For k=9 to 11 {
            M=A(k)=>Area()
            Print M
      }
      PressSpaceBar
      \\ before exit we push array to stack of values
      Push A()
}
\\ we call inside just  by name or using Call Inside (its not the same, but most of the times behave the same)
Inside
Print "Return from Inside Module"
\\ At this point there is nothing to tell us , or M2000 Interpreter that a superclass exist, and some other objects
\\ But there is an array  (with no name) at the top of stack of values
\\ Now we can define an array just by reading an array from stack of values
Read M()
\\ Lets see what we can do with objects in that array1
Z=M(1).Area()
Print Z
\\ We can use => for nameless objects
Z=M(2)=>Area()
Print Z

Try Ok {
      \\ this block needed to catch the error after
      \\ we get an error because we have "smart pointers" to names, but names aren't here (they erased)
      \\ so pointers
      Z=M(4)=>Area()
      Print Z
}
If Not Ok Then Print Error$
Z=M(7)=>Area()
Print Z
\\ also we can use dot and not => for array items which are pointers to groups or groups
Z=M(8).Area()
Print Z
Try Ok {
      \\ this block needed to catch the error after
      \\ we get an error because we have "smart pointers" to names, but names arren't here (they erased)
      \\ so pointers
      \\ M(9) to M(11) are pointers to same "named groups" as the M(3) to M(5)
      Z=M(10)=>Area()
      Print Z
}
If Not Ok Then Print Error$
\\ so from 12 items, we have 0 to 2, three real nameless groups, each one has a  pointer to same superclass
\\ although we didn't use the superclass to full strength, to supply common members for all subclass
\\ Three pointers to  these three groups in positions 6 to 8. All other positions have "broken" pointers.
\\ we can erase  group item using a zero Long literal
M(3)=0&, 0&, 9&
M(9)=0&, 0&, 0&
Print Type$(M(11))="Long"
\\ we can't use M(1)=>dim1+=100  because dim1 is private
for M(1) {
      .figure .getdim1+100, .getdim2
}
\\ because M(7) is a pointer to same object as M(1) we get  the change in M(7) too
Print M(7)=>getdim1
\\ we can get  a copy of object using Group() function
M(4)=Group(M(7))
\\ we can't use M(7)=>dim1-=100 because dim1 is private
for M(7) {
      .figure .getdim1-100, .getdim2
}
\\ because M(1) is a pointer to same object as M(7) we get  the change in M(1) too
Print M(1)=>getdim1
Z=M(4).Area()
Print Z
\\  now M(10) is a pointer, and M(4) is a pointer too same group, a copy of group which point the M(7) pointer.
M(10)->M(4)
Z=M(10).Area()
Print Z
\\ So in an environment which all objects are interpreted and not "compiled", we can use them without "blue prints", but actual as is.
For i=0 to 2 {
      Print M(i).AreaProp
}
For i=0 to 2 {
      Print M(i).AreaProp
}
For M(4) {
      Z=.Area()
      Print .AreaProp, .GetDim1, .GetDim2
      Print Z
}




Τρίτη 15 Μαΐου 2018

TextViewer (NotePad replacement)


 Πρόσφατα πήρα μια απλή έκδοση ενός NotePad, άλλαξα το στοιχείο ελέγχου TextBox  με ένα από το περιβάλλον της Μ2000 και τώρα μπορεί να κάνει πολλά και διάφορα, όπως φαίνεται στην εικόνα!