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

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

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

Αναθεώρηση 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, (δηλαδή θα χάσει "Φάση").  Αν κορεστεί το σύστημα, δηλαδή αν συμπληρώσει τη μη καταναλωμένη διάρκεια χρόνου, θα μεταθέτει όλα τα νήματα για πιο μετά! Επειδή υπάρχουν δυο πλάνα εκτέλεσης νημάτων, το διαδοχικό και το ταυτόχρονο. η συμπεριφορά που περιέγραψα ανήκει στο διαδοχικό. Το ταυτόχρονο κάνει το εξής, εκτελεί μια εντολή και κοιτάει αν αλλο νήμα έχει συνέχεια!  Εδώ ότι είναι σε μπλοκ εκτελείται χωρίς διακοπή. Στο ταυτόχρονο πλάνο, τα πράγματα είναι περισσότερο πολύπλοκα, και ξεφεύγουν από το σκοπό αυτής εδώ της αναφοράς!







Παρασκευή, 8 Δεκεμβρίου 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



Κυριακή, 3 Δεκεμβρίου 2017

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

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

Παρασκευή, 1 Δεκεμβρίου 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
 

Τετάρτη, 29 Νοεμβρίου 2017

Revison 17 (Version 9.0) new build, and How to go BASIC

In last build before this one, m2000.dll was from revision 16. So now is ok, and readme says "new build".



How to Go Basic
Some ideas to use M2000 as a Basic Interpreter.


\\ prepare M2000 to run close to basic
set switches "+FOR +DIM"
\\ using -FOR we enter loop 6 times.

For i=10 to 5 step 1 {
      Print "never enter"
}

Dim A(5)
\\ 6 elements if we use +DIM
For i=0 to 5 : Print A(I) : Next I

\\ Prepare Data using Flush
Flush
Data 10, 30,80,150,300,650,1640
\\ only Long needed to declare for numbers
\\ else is a double, or can be integer using % as last char.
Long M, S
While IsNum {
      M+=Number
      S++
}
\\ we can use = or == (double = use rounding before perform compare)
Print Round(M/S,3), Int(M/S)==408, Round(M/S,0)==409
Print Type$(M), Type$(S) \\ Long
Data 10, 30,80,150,300,650,1640
Sum%=0
Items%=0
Repeat {
      Read A%
      Sum%+=A%
      Items%++
} Until Empty
Print Round(Sum%/Items%,3), Int(Sum%/Items%)==408, Round(Sum%/Items%,0)==409
Print Type$(Sum%), Type$(Items%) \\ Double internal.

Print Eval("Sum%/Items%")

\\ Simply data inline code
Data "George", 51, "Alexander", 27, "Sofia", 24, "Fotini", 19
Min=1000 : Max=0
While not Empty {
      Read Name$, Age
      Print Name$, Age
      Min=Min.data(Min, Age)
      Max=Max.data(Max, Age)
}
Print Format$("Ages are form {0} to {1}", Min, Max)
\\ USING NO NESTED IF WITHOUT USING BLOCK OF CODES
If Ask("Choose 1 or 2","make your choise","1", "2")=1 Then Print "No good" : Print "if true only"
Else.If rnd>.5 then Print "Else.If" : Print "Only in else.if"
Else Print "Good" : Print "if else only"
\\ We have to use blocks
If true Then {
     If false Then {
            \\  nothing
       } Else.If false Then {
             \\ nothing
       } Else {
        Print "ok"
  }
}

100 N=100 ' N is double by default
110 Print N
120 N-=10
130 IF N>10 THEN 110 ' NO NEED TO WRITE GOTO 100
140 GOSUB ALFA(N)
150 GOSUB ALFA(N/2)
160 GOTO 200
170 SUB ALFA(X)
180 PRINT FORMAT$("{0:2:-10} | {0:2:10}", X)
190 END SUB

200 B=10
210 INPUT "Z=", Z
220 PRINT $("#0.000"),B*Z, B**2+Z, B^2+Z, $(""),,
230 DEF K(X)=X**2
240 PRINT K(Z)
245 REM ' TRY FILES
250 OPEN "FILE1" FOR OUTPUT AS M
260 WRITE #M, 100,200,300,400,500
270 CLOSE #M
280 OPEN "FILE1" FOR INPUT AS M
290 FOR I=1 TO 5 : INPUT #M, Z : PRINT Z: NEXT I
300 CLOSE #M

305 REM 'USE A STANDARD ROUTINE
310 M=10
320 GOSUB 350
330 IF M>0 THEN 320
340 END
350 M--
360 PRINT M
370 RETURN