Δευτέρα 18 Δεκεμβρίου 2017

Αναθεώρηση 26 (Έκδοση 9.0)

(Προσοχή αυτή η αναθεώρηση είχε πρόβλημα με τις λάμδα συναρτήσεις και έχει διορθωθεί)
Σε αυτήν την αναθεώρηση διόρθωσα μερικές ασυμβατότητες μεταξύ 8ης και 9ης έκδοσης. Προς το παρόν δεν υπάρχει ασυμβατότητα, έχουν ελεχθεί πολλά προγράμματα.
Επίσης αναπτύχθηκε καλύτερα η επιστροφή στο λάθος, δηλαδή όταν κάπου στο κώδικα έχουμε λάθος με το Shift + F1 μας πάει ο διερμηνευτής στο κώδικα. Σε άλλες γλώσσες αυτό είναι εύκολο αλλά για να μπορεί να γίνει πράξη ήθελε πολύ δουλειά, και ίσως ακόμα να χρειαστεί δουλειά.

Προστέθηκε η συνάρτηση Τάξη() ή Order() η οποία παίρνει δυο αλφαριθμητικά και τα συγκρίνει με ειδικό τρόπο: Οι αριθμοί εντός του αλφαριθμητικού είναι σημαντικοί, όταν τα γράμματα συμφωνούν. Πχ τα "Αλφα1000" και "Αλφα800" αν τα συγκρίναμε κανονικά θα έπρεπε επειδή το "Αλφα1" είναι μικρότερο από το "Αλφα8" να είχαμε τη σειρά Αλφα1000, Αλφα800, όμως η συνάρτηση Τάξη(), θα βρει πρώτα συμφωνία με τα γράμματα "Αλφα" και μετά θα δει τους αριθμούς ως αριθμούς, και το 800<1000, άρα θα βάλει το Αλφα800 και μετά το Αλφα1000. Δουλεύει ακόμα και αν έχουμε ίσους αριθμούς, μετά ίδια γράμματα και μετά πάλι αριθμούς. Ουσιαστικά κάθε φορά που αλλάζουμε από γράμματα σε αριθμούς είναι σαν να έχουμε άλλο κλειδί!

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


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


Ετοιμάζω το "Προγραμματίζοντας με τη Μ2000" 
Ο πίνακας δομών δεδομένων της Μ2000:
  • Τρέχον Σωρός Τιμών
  • Πίνακας με παρενθέσεις  και χωρίς (δείκτης σε πίνακα).
  • Κατάσταση (με μοναδικά κλειδιά) και Κατάσταση Ουρά (ακόμα και με ίδια κλειδιά). (και στις δυο περιπτώσεις έχουμε δείκτη στο αντικείμενο)
  • Αντικείμενο Σωρός Τιμών (δείκτης σε αντικείμενο Σωρός)
  • Διάρθρωση (διάρθρωση μνήμης) πίνακας απλών χωρίς πρόσημο στοιχείων ή δομών. (δείκτης σε Διάρθρωση).
  • Δομή (τύπος για τις διαρθρώσεις), είναι Κατάσταση εσωτερικά.
  • Έγγραφο (αλφαριθμητικό με παραγράφους)
  • Συνάρτηση Λάμδα (μπορεί να περιλαμβάνει κλεισίματα ως δεδομένα, και ίσως κάποια από αυτά να είναι δείκτες σε δομές δομένων)
  • Γεγονός (δεν περιλαμβάνει δεδομένα, αλλά λίστα συναρτήσεων, που μπορεί να έχουν δεδομένα ή να συνδέονται με ομάδες που έχουν δεδομένα)
  • Ομάδα (το κύριο αντικείμενο της Μ2000), μπορεί να περιλαμβάνει όλα τα παραπάνω, δικές της μεταβλητές, ιδιότητες, τελεστές, τμήματα, συναρτήσεις και άλλες ομάδες.
  • Υπερκλάση (ομάδα θεατή και κοινή για ομάδες, και αθέατη έξω από αυτές)
  • Φόρμες Παραθύρων
  • Στοιχεία φορμών παραθύρων.
  • Βάσεις δεδομένων (δομές στο δίσκο)
  • Αρχεία Κειμένου (δομές στο δίσκο)
  • Αρχεία Διαρθρώσεων Μνήμης (Διαρθρώσεις αποθηκευμένες στο δίσκο)
  • Αρχεία Εικόνας (οι εικόνες γράφονται τοπικά σε αλφαριθμητικά)


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






Φωλιασμένοι επαναλήπτες
Εφόσον ο δρομέας του επαναλήπτη είναι "προσωπικός" έχουμε το πλεονέκτημα να εφαρμόζουμε μαζί επαναλήπτες για την ίδια δομή. Υπάρχουν όμως δυο περιπτώσεις. Να έχουμε φωλιασμένους ή παράλληλους επαναλήπτες.
Κατάσταση Κ=1,4,6,8,78
Β=Κάθε(Κ, 1, 5)
Ενώ Β {
      Β1=Κάθε(Κ,5, 1)
      Ενώ Β1 {
                  Τύπωσε εκφρ(Β), εκφρ(Β1)
      }
      Τύπωσε
}



Το παραπάνω πρόγραμμα θα τυπώσει 5Χ5 φορές, ενώ το αμέσως επόμενο θα τυπώσει μόνο 5 φορές (τερματίζει η επανάληψη όταν τερματίσει ο πιο σύντομος επαναλήπτης):
Κατάσταση Κ=1,4,6,8,78
Β=Κάθε(Κ, 1, 5)
Β1=Κάθε(Κ, 5, 1)
Ενώ Β, Β1 {
                  Τύπωσε εκφρ(Β), εκφρ(Β1)
}



Για αυτόματους πίνακες:
Κ=(1,4,6,8,78)
Β=Κάθε(Κ, 1, 5)
Ενώ Β {
      Β1=Κάθε(Κ,5, 1)
      Ενώ Β1 {
                  Τύπωσε Πίνακας(Β), Πίνακας(Β1)
      }
      Τύπωσε
}

Κ=(1,4,6,8,78)
Β=Κάθε(Κ, 1, 5)
Β1=Κάθε(Κ,5, 1)
Ενώ Β, Β1 {
                  Τύπωσε Πίνακας(Β), Πίνακας(Β1)
}



Για Σωρούς Τιμών (η ΤιμήΣωρού() γυρνάει αριθμητική τιμή ή αντικείμενο):
Κ=Σωρός:=1,4,6,8,78
Β=Κάθε(Κ, 1, 5)
Ενώ Β {
      Β1=Κάθε(Κ,5, 1)
      Ενώ Β1 {
                  Τύπωσε ΤιμήΣωρού(Β), ΤιμήΣωρού(Β1)
      }
      Τύπωσε
}

Κ=Σωρός:=1,4,6,8,78
Β=Κάθε(Κ, 1, 5)
Β1=Κάθε(Κ,5, 1)
Ενώ Β, Β1 {
                  Τύπωσε ΤιμήΣωρού(Β), ΤιμήΣωρού(Β1)
}







Τετάρτη 13 Δεκεμβρίου 2017

Αναθεώρηση 24 (¨Εκδοση 9.0 - για το Wine)

Δυστυχώς στο Wine δεν μπόρεσε να λειτουργήσει η 23, γιατί δεν έχει 100% συμβατότητα το σύστημα του Wine με το σύστημα των Windows. Έτσι έβαλα όταν τρέχει σε Wine (το αναγνωρίζει), να μην προβαίνει σε έρευνα μεγέθους του σωρού επιστροφής (αφού υποχρεωτικά θα έπρεπε να σταματήσει όταν βγει λάθος, και να επιστρέψει, αλλά στο Wine - στο Linux- αυτό δεν επιστρέφει, κολλάει εκεί).

Τρίτη 12 Δεκεμβρίου 2017

Αναθεώρηση 23 (Έκδοση 9.0)

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

Σε αυτήν την αναθεώρηση μειώθηκε η χρήση του σωρού επιστροφής (process stack) του διερμηνευτή, μετά από κατάλληλες αλλαγές. Επιπλέον μπήκε σύστημα που ελέγχει το σωρό, γιατί τώρα ο διερμηνευτήγς "γνωρίζει" το μέγεθός του και πόσο έχει χρησιμοποιήσει.
Το πρόγραμμα m2000.exe που φορτώνει το m2000.dll δίνει στον διερμηνευτή 32MByte σωρό επιστροφής (ενώ 1MByte δίνει εξ ορισμού η Visual Basic, αλλά γίνεται να αλλάξει, κατά την παραγωγή του m2000.exe, στο αρχείο mexe.vbp υπάρχει το τμήμα [VBCompiler] και εκεί αλλάζουμε την τιμή του σωρού).
To m2000.exe είναι νέο, αν τρέξουμε το m2000.dll (τον διερμηνευτή δηλαδή) με παλιό m2000.exe θα έχει κατιτίς μικρότερο σωρό. Δείτε όμως μια διαφορά. Το νέο m2000.exe δίνει το μέγεθος στο m2000.dll με μήνυμα, ώστε να μην το ψάχνει. Στις άλλες περιπτώσεις το ψάχνει με τον απλό τρόπο..γεμίζει το σωρό -πολύ γρήγορα- μέχρι να βγει εσωτερικά λάθος! Σε κάθε αύξηση όμως καταγράφει το μέγεθος. Πώς όμως ξέρει ο διερμηνευτής το στιγμαίο μέγεθος (ή τωρινό θα το λέγαμε);
Καθώς ξεκινάει ο διερμηνευτής με την δημιουργία του αντικειμένου Μ2000.callback (αυτό καλεί το  m2000.exe γίνεται αυτό:
(κώδικας Visual Basic 6)
Dim anyname As Long
startaddress = VarPtr(anyname)

η anytime γράφεται στο σωρό τιμών, ενώ η startaddress είναι global, μόνιμη στην ουσία, ίσως εκτός σωρού! Αλλά αυτό που κάνουμε είναι να γράψουμε στην μόνιμη την θέση (διεύθυνση) του anyname, που είναι στο σωρό!  Με τον ίδιο τρόπο θα πάρουμε ανά πάσα στιγμή μια μέτρηση και με την διαφορά θα βρούμε το μέγεθος. Η διαφορά δεν είναι συνηθισμένη  γιατί τα νούμερα που παίρνουμε τα λογαριάζουμε ως μη προσημασμένων αριθμών. (unsigned long). Και τέτοιους αριθμούς δεν τους υποστηρίζει άμεσα η VB6, οπότε χρειάζεται μετατροπή. Μπορεί κανείς να δει το κώδικα της Μ2000 (είναι πάντα διαθέσιμος και στο git).

Πριν από αυτήν την αναθεώρηση υπήρχε ένας τρόπος απαρίθμησης κλήσεων συναρτήσεων, για να μην βγει οπουδήποτε το "out of stack", για να μην βγει καθόλου στην ουσία. Η απαρίθμηση ήταν ανά κλήση. Ενώ τώρα γίνεται κάτι άλλο. Συγκρίνεται λοιπόν το τωρινό μέγεθος με το μέγιστο.
Αυτό έδωσε το πλεονέκτημα να μπορούμε να έχουμε διαφορετικές αποδόσεις ανάλογα με τον τύπο κλήσης. Πράγματι υπάρχουν τρεις τύποι κλήσεων.
  • Η κλήση συνάρτησης μέσα από παραστάσεις. 
  • Η κλήση συνάρτησης/τμήματος με την Κάλεσε (το τμήμα έχει αναδρομή έτσι)
  • Η κλήση τμήματος από άλλο τμήμα
Στο τρίτο δεν έχουμε αναδρομή δηλαδή ένα τμήμα δεν μπορεί να καλέσει το όνομά του. Όμως αν έχουμε δυο γενικά τμήματα, μπορεί το ένα να καλεί το άλλο! Γιατί σε καθένα τμήμα θα είναι θεατό το άλλο, άρα μπορεί να κληθεί. Αυτό στην προηγούμενη αναθεώρηση ελέγχοταν όμως αριθμητικά όπως και η κλήση συνάρτησης. Όμως η κλήση αυτή είναι η πιο μικρή σε κατανάλωση σωρού, άρα για ίσο μέγεθος σωρού, δίνει περισσότερες κλήσεις σε σχέση με την κλήση συνάρτησης από παράσταση.
Με την εντολή Monitor ή Έλεγχος (στη γραμμή εντολών) θα δούμε τα Stack Limits (όρια σωρού) για τους τρείς τύπους (αν μόνο ο ένας από αυτούς κατανάλωνε όλο το σωρό)
Δίνει 3266 για αναδρομή σε συναρτήσεις, 5478 για κλήσεις με την Κάλεσε για τμήματα και συναρτήσεις, και 6419 για κλήσεις τμημάτων με το όνομά τους μόνο.

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

με edit D1 γράφουμε τα παρακάτω

global mm
function rec {
      mm++
      print mm, " ", monitor.stack
      =rec()
}
n=rec()

με edit D2 γράφουμε τα παρακάτω

global mm
function rec {
      mm++
      print mm, " ", monitor.stack
      call rec()
}
call rec()


με edit D3 γράφουμε τα παρακάτω
global mm
module global alfa1 {
      mm++
      print mm, " ", monitor.stack
      alfa2
}
module global alfa2 {
      mm++
      print mm, " ", monitor.stack
      alfa1
}
alfa1

αν το παραπάνω το κάναμε έτσι, θα πέφταμε στην περίπτωση του Call (όπως στο D2)
με edit D4 γράφουμε τα παρακάτω
global mm
module global alfa1 {
      mm++
      print mm, " ", monitor.stack
      call alfa2
}
module global alfa2 {
      mm++
      print mm, " ", monitor.stack
      call alfa1
}
call alfa1

Οι ρουτίνες δεν απασχολούν τον σωρό. Με το Όριο.Αναδρομής 0 αφαιρούμε το όριο, ή αν θέλουμε δίνουμε ένα! Οι ρουτίνες έχουν δικό τους σωρό επιστροφής, στο αντικείμενο που εκτελούνται (στο τμήμα ή στη συνάρτηση απ΄όπου καλούνται).


Τέλος εδώ είναι ένα Special μέρος! Έχει προγραμματάκια που έγραψα για να κατανοήσω το πρόβλημα Τόσο καιρό δεν είχα σκεφτεί ότι μπορούσα να μετρήσω το σωρό επιστροφής, και να δω τι κάνει η Visual Basic. Μπορεί να βλέπουμε μια κλήση πχ στην κλήση τμήματος αλλά δεν είναι έτσι ακριβώς μέσα στον διερμηνευτή, υπάρχουν επίπεδα κλήσεων που δεν βλέπουμε (ούτε φανταζόμαστε την χρήση τους).
Στο παρακάτω πρόγραμμα καλούμε την alfa(3) το (x) στον ορισμό θα γραφεί ως Read x (θα αποτελεί την πρώτη γραμμή του εκτελέσιμου κώδικα). Όταν η εντολή Print monitor.stack εκτελεστεί ήδη θα έχουμε μπεί στο Print (μια συνάρτηση εσωτερικά).

function alfa (x) {
      Print monitor.stack
100
      x--
      kappa(x*10)
      if x>1 then 100
      sub delta()
            Print n, monitor.stack
            if x>1 then call alfa(x-1)
           
      end sub
      sub kappa(n)
            delta()
      end sub
}
call alfa(3)

το ίδιο πρόγραμμα με τμήμα
module alfa (x) {
      Print monitor.stack
100
      x--
      kappa(x*10)
      if x>1 then 100
      sub delta()
            Print n, monitor.stack
            if x>1 then call alfa, x-1
           
      end sub
      sub kappa(n)
            delta()
      end sub
}
call alfa, 3

Δείτε τώρα πόσο "κατανάλωση έχει" το ίδιο πρόγραμμα με συναρτήσεις σε παραστάσεις:
Θα δώσω το πρώτο με αφαίρεση του πρώτου Print Monitor.Stack καθώς και στα δύο η κλήση θα γίνει για τον αριθμό 5 (βάλτε και παραπάνω)

function alfa (x) {
            x--
            Print x*10, monitor.stack
            if x>1 then N=Alfa(x-1): N=Alfa(x)
}
N=alfa(5)

Αυτό λοιπόν είναι ισοδύναμο με αυτό:

function alfa (x) {
\\      Print monitor.stack
100
      x--
      kappa(x*10)
      if x>1 then 100
      sub delta()
            Print n, monitor.stack
            if x>1 then call alfa(x-1)
           
      end sub
      sub kappa(n)
            delta()
      end sub
}
call alfa(5)

Από τα παραπάνω παρατηρούμε ότι οι ρουτίνες (sub kappa() και delta()) δεν έχουν καμία επίπτωση στο σωρό επιστροφής (αφού έχουν δικό τους σωρό, ο οποίος μπορεί να μεγαλώνει και για κάθε κλήση το μέγεθος είναι πολύ μικρό).
Επίσης δείτε ότι σε μια ρουτίνα είναι θεατές οι μεταβλητές του τμήματος. Η n όμως φτιάχνεται τοπικά στην Kappa και η delta την βλέπει γιατί στην κλήση από την Kappa το τμήμα έχει και την n. Όταν η Kappa τερματίσει, μετά την κλήση της delta() θα διαγράψει την n. Αν υπήρχε κάποια n στο τμήμα, τότε θα φαίνεται!

Επειδή η Μ2000 έχει νήματα και είναι και καθοδηγούμενη από γεγονότα, σημαίνει ότι όταν τρέξουν τα γεγονότα, θα φτιαχτούν ίσως νέες μεταβλητές, αλλά στην επιστροφή θα καθαρίσουν, και έτσι αυτό που έτρεχε και διέκοψε για να τρέξει το γεγονός, δεν λογαριάζει την "εισβολή". Στα νήματα ισχύει ότι δεν κάνουμε νέες μεταβλητές (μπορούμε όμως), επειδή έχουν το ίδιο όνομα χώρου με το τμήμα που τρέχουν (και το τμήμα μόλις τερματίσει διαγράφει τα νήματα που δημιούργησε). Κάθε νήμα όμως μπορεί να έχει τις δικές του στατικές μεταβλητές που δεν φαίνονται. σε άλλα νήματα. Οι στατικές μεταβλητές είναι εκτός λίστας μεταβλητών, επειδή ανήκουν στο αντικείμενο εκτέλεσης. Κάθε νήμα έχει δικό του αντικείμενο εκτέλεσης και έτσι έχει τις δικές του στατικές μεταβλητές και το δικό του σωρό τιμών. Όταν καλούμε μια ρουτίνα (το νήμα βλέπει τις ρουτίνες του τμήματος), από το νήμα, τότε ο διερμηνευτής δεν διακόπτει την κλήση, αλλά την αφήνει να τερματίσει (εκτός και αν διακοπεί από γεγονός, το οποίο θα πάρει προτεραιότητα).
Τα νήματα δουλεύουν σαν ρολόγια με την διαφορά ότι ο χρόνος εκτέλεσης είναι μέσα στο χρόνο επανάληψης. Δηλαδή βάζουμε κάτι να ξεκινάει κάθε 100ms, και έχει διάρκεια 20 ms, και τα υπόλοιπα 80ms θα τα πάρει το σύστημα. Αν όμως χρειαστεί διάρκεια 120 ms, τότε όχι μόνο θα περάσει κατά 20ms αλλά θα βάλει συν 100ms, (δηλαδή θα χάσει "Φάση").  Αν κορεστεί το σύστημα, δηλαδή αν συμπληρώσει τη μη καταναλωμένη διάρκεια χρόνου, θα μεταθέτει όλα τα νήματα για πιο μετά! Επειδή υπάρχουν δυο πλάνα εκτέλεσης νημάτων, το διαδοχικό και το ταυτόχρονο. η συμπεριφορά που περιέγραψα ανήκει στο διαδοχικό. Το ταυτόχρονο κάνει το εξής, εκτελεί μια εντολή και κοιτάει αν αλλο νήμα έχει συνέχεια!  Εδώ ότι είναι σε μπλοκ εκτελείται χωρίς διακοπή. Στο ταυτόχρονο πλάνο, τα πράγματα είναι περισσότερο πολύπλοκα, και ξεφεύγουν από το σκοπό αυτής εδώ της αναφοράς!







Σάββατο 9 Δεκεμβρίου 2017

Αναθεώρηση 22 (Έκδοση 9.0)

Στη αυτή την αναθεώρηση έκανα αρκετά πράγματα
1. Δουλεύει καλύτερα το σύστημα με πολλές οθόνες. Η εντολή Παράθυρο 16, 0 έβαζε παλιά το παράθυρο (την φόρμα της κονσόλας) με 16άρια γράμματα, και το 0 ήταν το "συνθημαιικό" για πλήρη οθόνη. Τώρα το συνθηματικό παίζει να είναι 0 για την Νο 1 οθόνη, 1 για την νο 2 οθόνη κ.ο.κ.

2. Η μεταβλητή Παράθυρο (νέα) δίνει τον αριθμό της οθόνης στο επίπεδο που καλούμε την μεταβλητή αυτή, και δίνει 0 για την Νο 1 οθόνη. Μπορούμε να επιθεωρήσουμε την κατάσταση οθονών με την Monitor, η οποία υπάρχει μόνο στα αγγλικά, και  η λέξη δεν εννοεί την οθόνη, αλλά την παρακολούθηση εσωτερικών διακοπών, και άλλων στοιχείων του διερμηνευτή.

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

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

μπορεί να ταξινομεί με πολλαπλά πεδία αριθμών στο κλειδί:
Εδώ έχουμε κλειδιά και πόλεις. ταξινομημένα!
KLM1234.5678.9 Preveza
KLM1234.5678.13 Patra
PRO0034.5678.6 Volos
PRO0034.5678.11 Volos
PRO1232.5678.44 Kalamata

 Έγγραφο α$
Κατάσταση α="KLM1234.5678.9":="Preveza", "KLM1234.5678.13":="Patra","PRO0034.5678.6":="Volos", "PRO1232.5678.44":="Kalamata", "PRO0034.5678.11":="Volos"
Ταξινόμηση α ως αριθμός
κάθε_κλειδί=Κάθε(α)
Ενώ κάθε_κλειδί {
      α$=Εκφρ$(α, κάθε_κλειδί^)+" "+Εκφρ$(α) +{
      }
}
Πρόχειρο α$

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

Στο παράδειγμα η alfa έχει το κλειδί 4 δυο φορές, στην μία έχει τιμή 30 και στην άλλη το 1000. Όσα κλειδιά δεν έχουν ειδικα τιμές, είναι τα ίδια τιμές (για διάβασμα μόνο)
 cls  ' just clear screen
inventory queue alfa=1,4:=30,2,6,3,4:=1000,2
\\ inventories are com objects inside M2000
\\ so we can manipulate internal properties
\\ with alfa, "inplace", false  \\ by default is true
\\ check withn 2000 or more items
for i=1 to 50 {
      append alfa, random(50000)
}
Print "Begin"
refresh
profiler   ' set HQ timer
sort descending alfa as number
sort ascending alfa as number
print timecount ' return miliseconds, but has many decimal parts.

6. Μπορούμε να ορίσουμε καταστάσεις σε μια εντολή Κατάσταση, και να δώσουμε και τιμές (παλιά θα δίναμε σε καμία ή στην τελευταία, αλλά όχι σε δυο η περισσότερες στην ίδια εντολή).

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


k=(1,2,3,4,5)
k1=Each(k,1, 3)
Print "k1"
While k1 {
      ' 3 times
      Print Array(k1)
}
k1=Each(k,1, 3) ' from start to 3rd
k2=Each(k,-1, 3) ' from end to 3rd (we can use here -3 as 3rd from last)
Print "k1, k2"
While k1, k2 {
      ' 3 times
      Print Array(k1)*Array(k2)
}
k1=Each(k,1, 3)
k2=Each(k,-1, 3)
Print "k1*k2"
While k1 {
      While k2 {
            ' 3x3 times
            Print Array(k1)*Array(k2)
      }
}



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

Στο παράδειγμα την Μήκος() την κάνουμε πίνακα μέσα στην Β(). αλλά στην επιστροφή λειτουργεί σωστά ως συνάρτηση που δίνει το  μήκος αλφαριθμητικών και αντικειμένων (πχ εδώ δίνει τον αριθμό στοιχείων του πίνακα Άλφα()).

Συνάρτηση Β {
      Πίνακας Μήκος(10)=100
      Μήκος(3)++
      Τύπωσε Μήκος(3) ' 101
      =Μήκος()
}

Πίνακας Αλφα()
Αλφα()=Β()
Τύπωσε Μήκος(Αλφα()) ' 10
Τύπωσε Αλφα(3) ' 101





Το παράδειγμα που εμφανίζει την εικόνα παραπάνω:

Form 80,50
? $(4) \\ set proportionl print
\\ report is always proportional
Report 2, {
     Using Inventory Example, to store keys as numbers or keys with numbers inside
     Inventory may have pairs of keys-values, or keys, or mix
     when a key has no values then key is a value also
     for key as value interpreter find if it is a number or a string, from starting letter
     if it is a number may have some characters after and is no problem but included in sorting if numbers are equal.
     
     
}
\\ need revision 21 and up
\\ unique keys only
inventory alfa="hello", 1,4,12,.324,32.423,"alfa","al1",23.2,"342 dpi",-343,-24,33,234, "al20", "al110","alfa[23][2]", "alfa[23][11]", "alfa[91][2]", "alfa[124][11]"
Print "Sort keys ascending"
Sort alfa as number
print alfa

Print "Sort keys descending"
Sort descending alfa as number
print alfa
here=row
Pen #ff5522 {Print  "Iterate from start"}
k=each(alfa)
def IsVal(m)=eval$(m) ~ "[-0-9.]*"
While k {
     if IsVal(k) then {
            Print val(eval$(k))
      } else {
            Print eval$(k)
      }
}

Pen #ff5522 { Print @(tab(3), here), "Reverse reading"}
k=each(alfa, -1, 1)
While k {
    Cursor tab(3)
     if IsVal(k) then {
            Print val(eval$(k))
      } else {
            Print eval$(k)
      }
}
Pen #ff5522 { Print @(tab(5), here), "Reverse reading only keys"}
k=each(alfa, -1, 1)
While k {
    Cursor tab(5)
            Print eval$(k, k^)

}
\\ clear alfa, using a new one without parameters
\\ using queue we can put any key, including same key
\\ but always we get the last of the same key
\\ we can't delete from anywhere, only using Drop command
Inventory queue alfa
Inventory alfa=1,11,2,2,3,5,-10
\\ only number Sort allowed
Sort alfa as number
Print alfa
\\ Drop iventory_name To expr  (drop  all items from item number plus one )
\\ Drop iventory_name  expr  (drop last items)
\\ Drop iventory_name,  expr  ' same as above, comma is optional from this revision
Drop alfa 4
Print "Drop 4 from end"
Print alfa
Print "Append 4 items - no sorting"
Append alfa, 7,2,7,6
Print alfa
Print "Sorting ascending"
Sort ascending alfa as number ' ascending is optional here - by  default is in ascending order
Print alfa
Drop alfa to 5
Print "Drop from 5+1, so we keep 5 items"
Print alfa



Δευτέρα 4 Δεκεμβρίου 2017

Αναθεώρηση 20 Έκδοση 9.0

Σε αυτήν την αναθεώρηση έβγαλα ένα πρόβλημα που βρήκα στην 19, έκανα πολλές δοκιμές, και ο διερμηνευτής δουλεύει καλά. Ξεκίνησα την υποστήριξη δυο ή και περισσότερων οθονών. Δεν έχει τελειώσει ο κώδικας, αλλά από αυτή την έκδοση μπορούμε να μετακινούμε την κονσόλα σε άλλη οθόνη, και τα παράθυρα που φτιάχνουμε επίσης. Έχει ακόμα δουλειά, και πολύ έλεγχο. Σε αυτή την αναθεώρηση άλλαξαν 31 αρχεία!

Σάββατο 2 Δεκεμβρίου 2017

Βίντεο από την έκδοση 9.0 (αναθ. 19)

Στο βίντεο τρέχουν διαδοχικά δυο προγράμματα, στα οποία τρέχουν νήματα. Η Μ2000 έχει ενσωματωμένο ένα σύστημα νημάτων. Τα νήματα τα διαχειρίζεται ένας ενσωματωμένος διαχειριστής. Τα προγράμματα που βλέπουμε στο βίντεο έχουν δημοσιευτεί σε αυτό το φόρουμ, και έτρεχαν σε παλιότερες εκδόσεις. Αυτό που δεν έκαναν οι παλιές εκδόσεις ήταν να δείχνουν τα νήματα στη φόρμα ελέγχου. Από την 8η έκδοση τα νήματα μπορούσαν να φανούν στην φόρμα όπως θα δείτε στο βίντεο.
Έκανα ένα τεστ για το νέο διερμηνευτή (έχει αλλαγές που βελτιώνουν την ταχύτητα). Τα Windows 7 τρέχουν σε VirtualBox, σε Ubuntu Studio 64 bit  και ταυτόχρονα γίνεται σύλληψη βίντεο. Παρόλα αυτά η ταχύτητα είναι καλή.

Στο πρώτο πρόγραμμα ένα νήμα μεταφέρει μια τεθλασμένη γραμμή, ένα άλλο επίσης μια άλλη γραμμή με λεζάντα και ώρα, και η οποία "ακούει" στα άνω και κάτω βελάκια.
Στο δεύτερο πρόγραμμα χρησιμοποιώ έναν "παίκτη" της κονσόλας της Μ2000, που είναι ένα hardware sprite, στην ουσία ένα "παράθυρο" που το διαχειρίζεται η κάρτα γραφικών. Επιπλέον υπάρχουν μερικές ακόμα διαφάνειες οι οποίες είναι μέσα στην οθόνη και για το λόγο αυτό μπορούν να εμφανιστούν πίσω από τα βουνά που "ολισθαίνουν" (έτσι φαίνεται, αλλά δεν είναι έτσι). Και τα hardware sprites, όπως και τα software, μπορούν να περιστραφούν. Εκτός από τις εικόνες που διαδοχικά αλλάζουν, το περιβάλλον του διερμηνευτή, περιστρέφει και τις μεγεθύνει κατάλληλα.

Παρατηρήστε ότι δεν φαίνεται το βελάκι του ποντικού πάνω από την κονσόλα. Επίσης δείχνω πως και η κονσόλα είναι ένα παράθυρο, και μπορεί να μετακινηθεί, να αλλάξει μέγεθος, και στο νέο μέγεθος να δημιουργήσουμε αναλύσεις κειμένου με την εντολή Φόρμα.

Παρατηρήστε επίσης τη φόρμα ελέγχου. Η Μ2000 έχει δικά της παράθυρα, τις ειδικές φόρμες, όπως η φόρμα ελέγχου, και άλλες για επιλογές φακέλων, αρχείων, εικόνων, χρωμάτων, γραμματοσειράς, ρυθμίσεων, βοήθειας, το message box (η συνάρτηση Ρώτα() ανοίγει το ενσωματωμένο messagebox, δείτε τη βοήθεια σχετικά), καθώς και τις φόρμες χρήστη. Δηλαδή μπορούμε να φτιάχνουμε δικά μας παράθυρα με στοιχεία ελέγχου και να παίρνουμε τα μηνύματα. Δείτε εδώ το Notepad, μια εφαρμογή σημειωματάριου με μενού, γραμμένη σε Μ2000.




Αναθεώρηση 19 (Έκδοση 9.0) - Προσθήκες!

1) Στην Άλλαξε (Swap) τώρα ο διερμηνευτής δεν επιτρέπει να κάνουμε αλλαγή μεταβλητής με σταθερά.
2) Μπορούμε να ορίσουμε Τελικά τα Τμήματα/Συναρτήσεις/Τελεστές μιας ομάδας, ώστε να μην μπορούν να αλλαχτούν.
3) Μπορούμε να ορίσουμε τελικές μεταβλητές που θα πάρουν αργότερα μια τιμή αλλά όχι δεύτερη. Η αρχική τιμή είναι 0 ή αν διαβάσουμε το τύπο είναι Constant (Σταθερή). Υποστηρίζονται οι τύποι πραγματικός (double), ακέραιος (%), και αλφαριθμητικό ($)
4)Μπορούμε να ορίσουμε πίνακες (ονόματα με παρενθέσεις), ως τελικό, και μπορούμε να τον γεμίζουμε σταδιακά, πάλι όμως μια δεύτερη τιμή θα βγάλει λάθος! Οι πίνακες αυτοί αν αντιγραφούν σε άλλο πίνακα, δεν μεταφέρουν το χαρακτηριστικό"Τελικό". Όμως αν αντιγραφεί το αντικείμενο ομάδα, τότε θα έχουμε αντιγραφή με χαρακτηριστικό τελικό.
5) Μπορούμε να εισάγουμε τιμές σε αντικείμενα ομάδες που διαβάζουν τιμές (σαν μεταβλητές), με την Εισαγωγή.



Παραδείγματα

Group alfa {
      final kappa$, p=3.14
}
list
alfa.kappa$="hello"
Print alfa.kappa$, alfa.p
list
Try {
      alfa.kappa$="Bye"  ' can't assign second value
}
Try {
      alfa.p+=100 ' can't assign second value
}
list


Άλλο παράδειγμα:


Class alfa {
      final a(4)
      a(0)=1,2,3,4
}
Dim K(2)
K(1)=alfa()
Print K(1).a(2)
\\K(1).a(2)=100   ' error
m=K(1).a()
Print m
dim b()
a=K(1).a()
b()=a ' get a copy
b(1)+=100
Print b(1)
beta=alfa() \\ copy group to beta
Print beta.a()
\\beta.a(2)+=5  ' error



Αφαιρέστε το Final για να δείτε τι βγάζει το πρόγραμμα!


Group alfa {
      x=100
      Function final delta (x) {
            =x**2
      }
      module final kappa {
            Print .delta(.x)
      }
}

alfa.kappa
group alfa {
      Module kappa {
            Print "10000000", .x
      }
}

alfa.kappa
dim a(10)
a(3)=alfa
beta=a(3)
beta.kappa
a(3).kappa
? a(3).delta(4)

Module beta.kappa {
      Print "10000000", .x
}
Function beta.delta (z) {
      =z*100
}
beta.kappa
? beta.delta(4)


Παράδειγμα όπου διαβάζουμε ένα αντικείμενο στο οποίο έχουμε ορίσει να δίνει και να παίρνει τιμή.Όταν παίρνει τιμή έχουμε ορίσει να έχει και έναν δείκτη. Στην εντολή Input (Εισαγωγή) πληκτρολογούμε αυτό που θέλουμε και το διερμηνευτής το στέλνει στην m$ και τον δείκτη στην n.

Group alfa$ {
      m$="ok"
      n
      value {
            =.m$
      }
      set (.n) {
            read .m$
      }
      module ok {
            print "ok", .m$, .n
      }
}
Input alfa$(3)
Print alfa.n
alfa.ok
list