Παρασκευή, 22 Ιουνίου 2018

Αναθεώρηση 14 (Έκδοση 9.3)

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

Στο παράδειγμα (έστω το έχουμε γράψει στο τμήμα Α, με την Σ Α ανοίγουμε το διορθωτή και αντιγράφουμε το παρακάτω και πατάμε Esc):

Ομάδα Α {
      Χ=10
      Πίνακας Μ(10)=4
}
Α=Α
Λίστα

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

Το δεύτερο λάθος ήταν πιο δύσκολο: Έπρεπε να επαναφέρω μια λειτουργία που εμφανίστηκε στις αρχικές αναθεωρήσεις της έκδοσης 9.3 (Δείτε εδώ) και εδικότερα στο παρακάτω:
Group alfa {
      x=10
}
inventory beta="10":=alfa
Group n=beta("10")
Print n.x=10
Print beta("10").x=10
a->Beta("10")
for Beta("10") {
      Print .x=10
       a=>x++
      Print a=>x=11
}
a=>x+=100
Print a=>x=beta("10").x ' true
a=>x++
Print beta("10").x=112
beta("10").x++
Print beta("10").x=113
Print a=>x=113

Δεν είναι εύκολα κατανοητό το τι θέλει να δείξει το πρόγραμμα:
Ανοίγουμε το Beta("10") το οποίο είναι η ομάδα στη Κατάσταση Beta(), στο κλειδί "10". Η ομάδα είναι "κλειστή" και με την For (ή Για στα ελληνικά), έχουμε μια ανοιχτή ομάδα, με κρυφό όνομα, όπου το .x αναφέτεται στο μέλος x. Έχουμε ήδη φτιάξει το a ως δείκτης σε αυτή την κλειστή ομάδα. Όταν δίνουμε το a=>x++ ο διερμηνευτής πάει να ανοίξει το κλειστό αντικείμενο αλλά βλέπει ότι είναι ήδη ανοικτό, και αλλάζει την τιμή του x, και το αποθηκεύει κιόλας. Όταν τελειώνει το For {} θα αποθηκευτεί πάλι αλλά δεν μας πειράζει. Στην ουσία εμείς βλέπουμε ότι ο δείκτης a λειτούργησε. Στην πράξη υπήρχαν δυο αντικείμενα, το κλειστό και το ανοιχτό, αλλά στο κλειστό είχε γραφτεί το κρυφό όνομα του ανοιχτού και από εκεί το βρήκε το α=>χ++, όπως και το α=>x=11

Δουλεύει και έτσι:
 
Group alfa {
      x=10
}
inventory beta="10":=alfa
Group n=beta("10")
Print n.x=10
Print beta("10").x=10
a->Beta("10")
For Beta("10"), a {
      Print .x=10
      ..x++
      Print ..x=11
}
a=>x+=100
Print a=>x=beta("10").x ' true
a=>x++
Print beta("10").x=112
beta("10").x++
Print beta("10").x=113
Print a=>x=113


Δουλεύει και με υπορουτίνα:

Group alfa {
      x=10
}
inventory beta="10":=alfa
Group n=beta("10")
Print n.x=10
Print beta("10").x=10
a->Beta("10")
For Beta("10") {
      Print .x=10
      IncX(a)
}
a=>x+=100
Print a=>x=beta("10").x ' true
a=>x++
Print beta("10").x=112
beta("10").x++
Print beta("10").x=113
Print a=>x=113

Sub IncX(a)
      a=>x++
End Sub

Θα μπορούσαμε να γράψουμε τη ρουτίνα έτσι:

Sub IncX(a as pointer)
      a=>x++
End Sub

Στο παράδειγμα που ακολουθεί κάνουμε την IncX να πάρει λάθος αντικείμενο, να πάρει δείκτη έμμεσο, και δείκτη άμεσο. Ο έμμεσος δείκτης είναι στην ουσία ισχνή αναφορά. Όταν χρειάζεται να επιλύσει την ισχνή αναφορά ο διερμηνευτής θα δει αν υπάρχει τo k, και αν όχι θα βγάλει λάθος. Ο άμεσος δείκτης δείχνει πάντα κλειστό αντικείμενο (δεν έχει δηλαδή όνομα). Να θυμήσω εδώ ότι μπορεί να έχει τελικά όνομα το κλειστό αντικείμενο γιατί μπορεί ένας άλλος δείκτης σε αυτό να το έχει "ανοίξει" με κρυφό όνομα. Παρόλα αυτά και εδώ είναι που λύθηκε το λάθος, θα το "καταλάβει" ο διερμηνευτής και θα το χειριστεί κατάλληλα.
Για να δώσουμε από δείκτη αντίγραφο για συγχώνευση πρέπει να χρησιμοποιήσουμε τη συνάρτηση Ομάδα() ή Group()


Group k {
      x=10
}
Try ok {
      IncX(k)
}
If not ok then print Error$ ' Wrong object type
Z->k ' έμμεσος δείκτης επειδή το k είναι στατικό αντικείμενο
incX(Z)
Print Z=>x
Z->(k) ' κανονικός δείκτης επειδή το (k) είναι νέο αντικείμενο (Αντίγραφο του k)
incX(Z)
Print Z=>x
Print k.x = Z=>x-1 'Αληθές
k=Group(Z)
Print k.x = Z=>x ' Αληθές
\\ η Sub δουλεύει και ως Exit αν τη συναντήσει η ροή εκτέλεσης
Sub IncX(a as pointer)
      a=>x++
End Sub

Και με ελληνικές εντολές:

Ομάδα Κ {
      χ=10
}
Δες οκ {
      ΑύξησεΧ(Κ)
}
Αν όχι οκ Τότε Τύπωσε Λαθος$ 'Λάθος τύπος αντικειμένου
Ζ->Κ ' έμμεσος δείκτης επειδή το Κ είναι στατικό αντικείμενο
ΑύξησεΧ(Ζ)
Τύπωσε Ζ=>χ
Ζ->(Κ) ' κανονικός δείκτης επειδή το (Κ) είναι νέο αντικείμενο (Αντίγραφο του Κ)
ΑύξησεΧ(Ζ)
Τύπωσε Ζ=>χ
Τύπωσε Κ.χ = Ζ=>χ-1 'Αληθές
Κ=Ομάδα(Ζ)
Τύπωσε Κ.χ = Ζ=>χ ' Αληθές
\\ η Ρουτίνα δουλεύει και ως Έξοδος αν τη συναντήσει η ροή εκτέλεσης
Ρουτίνα ΑύξησεΧ(α ως δείκτης)
      α=>χ++
Τέλος Ρουτίνας