Προς το περιεχόμενο

Ενημέρωση για τη Μ2000 (Γλώσσα προγραμματισμού)


M2000

Προτεινόμενες αναρτήσεις

Δεν είναι στους άμεσους στόχους μου η σύνδεση της Μ2000 με το tcp/ip.

 

Πολύ κακώς. Εφ' όσων είναι μία εκπειδευτική γλώσσα, θα έπρεπε να μπουν οι μαθητές στο τριπάκι να κάνουν -- for say -- μια chat εφαρμογη.

 

Το να λες ότι είναι εκπαιδευτική, λέγοντας το struct <<Δομη>> και να είναι το ίδιο βαρετή για έναν μαθητή με τη ΓΛΩΣΣΑ, τοτε είανι χαμενο το παιγνίδι.

 

Και στη τελική, μια τελευταία ερώτηση, με όλο το θαρρος. Αφού στο πρώτο σου πόστ λές:

 

Λίγα λόγια για τη γλώσσα:

Η γλώσσα είναι διερμηνευτής που τρέχει σε δικό του περιβάλλον. Τα αρχεία που χρησιμοποιεί είναι αρχεία κειμένου σε Utf8. Όλες οι εντολές είναι και σε αγγλικά και σε ελληνικά. Η γλώσσα δεν είναι wrapper μιας άλλης γλώσσας, αλλά είναι πρωτότυπη, δηλαδή έχει στοιχεία που δεν έχουν άλλες γλώσσες (όπως και το ανάποδο, δεν έχει στοιχεία που έχουν άλλες γλώσσες). Αυτό που σίγουρα έχει είναι ότι πλησιάζει το 99% της Basic, Ενώ η Basic δεν φτάνει ούτε το 20% από την Μ2000. Και αυτό γιατί η Μ2000 έχει αντικείμενα, που η Basic δεν έχει (τέτοια αντικείμενα δεν έχει ούτε η VB6 στην οποία έχει γραφτεί η γλώσσα).

 

 

Πώς, εφ' όσων χρησιμοποιείς ΜΟΝΟ κλάσεις της VB6;

 

Προσπάθησα και στο blog και εδώ να βρώ διαφορές απο την VB και πραγματικά παλεύω να τις βρώ. Άρα η γλώσσα σου δεν είναι και τόσο πρωτότυπη.

 

(πάντα φιλικά)

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημοσ. (επεξεργασμένο)

Καλά κάνεις και το συζητάς το θέμα! Σε ευχαριστώ κιόλας που είχες τη καλοσύνη να ασχοληθείς και με το blog. Για το θέμα πελάτη εξυπηρετητή δουλεύει η Μ2000 με namedpipes εσωτερικά και με ένα απλό τρόπο για το χρήστη. Ένα νήμα της γλώσσας κρατάει την εισαγωγή. Μπορεί κανείς να ανοίξει και δεύτερο και τρίτο κανάλι αλλά δεν βοηθάει...γιατί: Ο τρόπος που το χρησιμοποιώ είναι να διαβάζει ασύγχρονα. Για να στείλει γίνεται το εξής..αν  δεν μπορεί να στείλει βγαίνει λάθος. Αυτό σημαίνει ότι θα στείλει την επόμενη φορά, ή ότι δεν υπάρχει τίποτα για να πάρει. Μπορεί κανείς να βάλει την ρουτίνα που στέλνει σε νήμα, άρα να λειτουργεί ασύγχρονα. (δεν μπλοκάρει εσωτερικά η αποστολή, γιατί ή γίνεται άμεσα ή δεν γίνεται...και βγάζει λάθος). Τα namedpipes δουλεύουν σε ένα LAN, και νομίζω ότι δεν δουλεύουν με TCP/IP...(εδώ ίσως γνωρίζεις περισσότερα).

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

 

Γιατί η Μ2000 δεν είναι wrapper της VB6.

Να το δούμε κατασκευαστικά; Η VB6 είναι ένας compiler, που ετοιμάζει ένα πρόγραμμα με κλήσεις σε εξωτερικές βιβλιοθήκες και ένα μέρος τους υποχρεωτικά στη βιβλιοθήκη (DLL) το λεγόμενο και runtime. Μπορεί κανείς να έχει το τελικό πρόγραμμα ως p-code ή σε γλώσσα μηχανής. Αυτό που δίνει δηλαδή είναι ένα exe αρχείο. Το γιατί παίζει το "runtime", ενώ έχουμε π.χ. γλώσσα μηχανής να εκτελείται, δεν είναι εδώ θέμα, έχει δοθεί εξήγηση σε προηγούμενη ανάρτηση.(αλλά αν θέλει κανείς ξαναρωτάει να το κάνω πιο λιανά)

Η Μ2000 είναι ένας διερμηνευτής. Τρέχει source πάντα. Το περιβάλλον της, το m2000.exe είναι γραμμένο σε VB6. Δεν έχει πολλές εξαρτήσεις και για το λόγο αυτό τρέχει από τα XP έως και στα 10 χωρίς κάποια βιβλιοθήκη συνοδευτική. Δεν θέλει καν εγκατάσταση. Εγώ τοποθετώ το m2000.exe και το help αρχείο (δεν είναι απαραίτητο για να τρέξει να υπάρχει το αρχείο αυτό), σε ένα φάκελο στα έγγραφά μου.

 

Να πάμε στο συντακτικό; Έχει ομοιότητες αλλά και διαφορές.

(συνεχίζεται)

Επεξ/σία από M2000
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

1. Η VB6, έχει φόρμες, κλάσεις, τμήματα (modules). H M2000 φτιάχνει δυναμικά φόρμες, άρα δεν έχουμε ξεχωριστή οντότητα φόρμα που θα δηλωθεί από την αρχή. Για να γίνει κατανοητό αυτό. Φτιάχνουμε στην VB6 πέντε φόρμες; Θα έχουμε πέντε ή περισσότερες φόρμες από αυτές τις πέντε. Αν υποθέσουμε ότι θέλαμε να φτιάξουμε μια φόρμα που δεν έχει δηλωθεί στο πηγαίο κώδικα, τότε θα πρέπει να έχουμε μια κενή φόρμα. Το πρόβλημα είναι ότι τα μηνύματα για τη φόρμα αυτή βρίσκονται μέσα στο κώδικα της φόρμας...άρα δεν θα μπορούμε να πάρουμε τα μηνύματα (από τα events)... Υπάρχει ένα ψέμα εδώ! Και εγώ όπως και άλλοι αυτό καταλαβαίναμε, αφού για να πάρεις ας πούμε το command1_click Θα πρέπει να υπάρχει ο κώδικας στην φόρμα, που βρίσκεται το button με όνομα command1. Αν θέλεις να προσθέσεις με όνομα που δεν ξέρεις τότε πώς είναι δυνατόν να βάλεις κώδικα στη φόρμα για αυτό, στην εκτέλεση! Κάποιοι σκέφτονται το sub classing, δηλαδή θα παίρνουμε τα μηνύματα. Αλλά και πάλι έχουμε θέμα αναγνώρισης αν έχουμε δυο τρία ίδιου τύπου στοιχεία.Δείτε όμως τι έκανα:

 

Η πατέντα που έχω κάνει με τη Μ2000 είναι ότι έχω φτιάξει μια φόρμα "γενικού σκοπού", η οποία ενημερώνεται για τα στοιχεία που τις βάζω...και χρησιμοποιώ ενδιάμεση κλάση η οποία αυτή παίρνει τα μηνύματα και χρησιμοποιεί μια συγκεκριμένη συνάρτηση  CallBack στην "μαμά" φόρμα, απ' όπου καλεί το γεγονός στην Μ2000, και όχι όπου τυχαία αλλά η φόρμα έχει αναφορά στο όνομα του τμήματος, άρα όταν καλέσει το Click() event, τότε καλεί με το όνομα του στοιχείου και το αναγνωριστικό του γεγονότος, αν υπάρχει συνάρτηση τέτοια (το βρίσκει άμεσα με πίνακα κατακερματισμού, εκτελώντας δηλαδή μόνο την συνάρτηση που δίνει ένα νούμερο και άμεσα ξέρει αν υπάρχει το γεγονός ως συνάρτηση, και αν ναι την καλεί).

Αν θέλω να βάλω ένα ListBox τότε θα δημιουργήσω ένα αντικείμενο εσωτερικά (αθέατο στο χρήστη της Μ2000) το GuiListBox το οποίο έχει όλα τα events από ένα Glist (το μοναδικό usercontrol) το οποίο φορτώνεται στην φόρμα που δηλώνω στον ορισμό με την εντολή Όρισε (Declare). To GuiListBox δεν είναι πάνω στην φόρμα, και όμως παίρνει τα events του Glist που είναι πάνω στην φόρμα. Δεν έχω κάνει wrap στοιχείο listbox της VB6, το glist είναι δικό μου στοιχείο, και έχει δημοσιευτεί καιρό τώρα. Αν σβήσουμε την φόρμα τότε η φόρμα "γνωρίζει" την ύπαρξη του GuiListBox και καλεί μέθοδο σε αυτό που αποδεσμεύει το Glist. Έτσι μένει το όνομα με ένα άδειο αντικείμενο (άδειο από στοιχείο), το οποίο αν χρησιμοποιηθεί θα γυρίσει σφάλμα. Στο πέρας της εκτέλεσης του τμήματος οι μεταβλητές σβήνονται. Επίσης στα αντικείμενα αυτά δεν μπορούμε να βγάλουμε αναφορές (και έτσι να τα κρατήσουμε "στη ζωή"), άρα έχουμε ασφάλεια, από άποψη μη σωστής διαχείρισης της μνήμης.

 

Εδώ θα ήθελα να αναπτύξω πως τελικά φθάνουν τα μηνύματα από τα "εξωτερικά" αντικείμενα που συλλέγουν τα γεγονότα του δικού τους glist, αλλά το αφήνω για άλλη φορά. Επίσης υπάρχει και ένα μυστήριο στοιχείο, το Combo, το οποίο έχει δυο στοιχεία και μια φόρμα. Το ένα στοιχείο είναι ένα TextBox και το άλλο είναι ένα Listbox πάνω σε μια νέα φόρμα (παράθυρο). Όλα τα γεγονότα από τα δυο στοιχεία και το παράθυρο τα παίρνει ένα GuiDropDown αντικείμενο. Σημειώστε δε ότι η Μ2000 κρατάει τιμές και αντικείμενα πάντα σε έναν πίνακα, που αυξομειώνει, όχι και τόσο γρήγορα...βέβαια, ενώ τα ονόματα τους τα κρατάει ένας πίνακας κατακερματισμού, ο οποίος έχει την ιδιομορφία να αυξάνει και αυτός με γρήγορο rehashing (είχα φτιάξει ένα παράδειγμα για πίνακα κατακερματισμού σε Μ2000 και μου άρεσε τόσο πολύ που τον έγραψα μετά σε Vb6 - το ίδιο έκανα και με το Event αντικείμενο, πρώτα το έφτιαξα σε M2000), και επίσης υπάρχει άλλη μια ιδιομορφία, τα ονόματα μπορούν να είναι περισσότερα από τις τιμές γιατί έχουμε και αυτά τα ονόματα που είναι αναφορές σε τιμές. Εδώ μπορεί να δει κανείς στο κώδικα τι γίνεται..διότι μπορεί στο τμήμα Β που καλέστηκε από το Α να είναι η μεταβλητή Κ που είναι αναφορά της Δ στην Α. Εδώ ο πίνακας κατακερματισμού σημειώνει ξεχωριστά τις αναφορές ώστε να καθαρίσει τον δείκτη της όταν φύγει και η τελευταία αναφορά, στο παράδειγμα όταν τερματίσει η Α άρα καθαρίσει η Δ. Ένα αντικείμενο που περνάει έτσι είναι ο πίνακας με αναφορά, και το λάμδα, αλλά όχι το αντικείμενο ομάδα. (Για αυτό θα δούμε άλλη φορά).

 

Συναρτήσεις λάμδα δεν έχει η Vb6. Το ότι έχουν φτιαχτεί με αυτήν δεν σημαίνει ότι η Vb6 απέκτησε συναρτήσεις λάμδα. Και εδώ είναι η ουσία σε αυτό που λέω "η Μ2000 γράφτηκε με Vb6, για να κάνει πράγματα που δεν κάνει η Vb6". Και να χτυπιέται κανείς λάμδα συναρτήσεις δεν μπορεί να βάλει στην VB6. Δεν μπορείς πχ. να πάρεις ένα αντικείμενο να το βάλεις σε μια συνάρτηση και να το δώσεις ως επιστροφή συνάρτησης..Στη Μ2000 γίνεται! Απλά το αντικείμενο θα είναι πια εντός της λάμδα, χωρίς καμία πρόσβαση απ'έξω., ο μόνος τρόπος είναι να δώσουμε τιμές στην Λάμδα (η Μ2000 δεν προκαθορίζει αριθμό και τύπο στοιχείων που δίνουμε σε τμήματα και συναρτήσεις)

 

 

2. Περί τμημάτων,

Στη VB6 όλα τα τμήματα έχουν ένα επίπεδο...το Public και ένα το Private. Αν έχω τρια Bas αρχεία, και έχω δηλωμένες τις SUBs alfa(), beta() τότε η alfa() μπορεί να καλέσει την beta() αν είναι public,

Στη Μ2000 τα τμήματα που είναι γενικά πράγματι μπορούν να λειτουργήσουν έτσι.

Οι διαφορές αρχίζουν όταν δούμε ότι η Μ2000 έχει φωλιασμένες συναρτήσεις και τμήματα. Εδώ έχουμε διαφορά και με την java. Έστω στο τμήμα alfa έχουμε τα τμήματα beta και delta. Πριν καλέσουμε την alfa τα beta και delta δεν είναι "δημοσιευμένα", δεν υπάρχουν δηλαδή, παρά μόνο ως ορισμοί στην alfa. Δεν μπορούμε να καλέσουμε το Alfa.beta Πρέπει να τρέχει το Alfa και ο ορισμός του beta να περάσει από την ροή εκτέλεσης για να υπάρχει το beta (θα μπορούσαμε να είχαμε εναλλακτικούς ορισμούς, ή να τον φορτώναμε από το δίσκο). Στο τμήμα beta δεν υπάρχει καμία ένδειξη για το ποιος κάλεσε το τμήμα, ούτε μπορούν να φανούν οι μεταβλητές του Alfa. Αν στο Alfa φτιάξαμε το delta πριν καλέσουμε το Beta τότε για το Beta το delta δεν υπάρχει. Θα υπάρχει delta στο Beta μόνο αν το Alfa φτιάξει το delta ως global (γενικό). Επίσης δεν βλέπει το Beta ούτε τον εαυτό του. Τα τμήματα εξ ορισμού ΔΕΝ κάνουν αναδρομή, δεν καλούν τον εαυτό τους. Υπάρχει τρόπος αλλά δεν θα τον εξηγήσω εδώ, γιατί η εξήγηση προϋποθέτει και άλλη γνώση για το πώς είναι τα τμήματα εσωτερικά. Ένα τμήμα κληρονομεί το σωρό τιμών του πατρικού τμήματος. Ο σωρός τιμών δεν υπάρχει στην VB6. Όταν καλούμε ένα τμήμα και βάζουμε δυο παραμέτρους αυτές πάνε στο σωρό τιμών. Αν βάλουμε τις παραμέτρους στο σωρό και μετά καλέσουμε το τμήμα, πάλι θα πάνε οι τιμές στο τμήμα. Απλά όταν καλούμε το τμήμα π.χ. ΑΛΦΑ 12+2, 5 θα κάνει ο διερμηνευτής το εξής, θα φτιάξει ένα νέο σωρό θα βάλει το 15 στην ουρά του, άρα στο πρώτο στοιχείο, αφού είναι κενός, μετά θα βάλει το 5, πάλι στην ουρά, άρα στην κεφαλή είναι το 15, και μετά θα βάλει το σωρό στην κεφαλή του τρέχοντος, άρα θα πάει το 15 στην κορυφή. Και οι συναρτήσεις έχουν σωρό...Π.. η ΑΛΦΑ βήτα(10) θα κάνει το εξής, πρώτα θα δει ο διερμηνευτής το ΑΛΦΑ ότι υπάρχει, αλλιώς θα βγάλει λάθος, μετά θα δει τι έχει ως πρώτη παράμετρο (αν έχει), δεν ξέρει τι είναι αλλά  θα πάρει ότι του δώσουμε. Εδώ θα εκτελέσει την βήτα( η οποία και αυτή δεν ξέρει τι πρέπει να πάρει, θα πάρει ό,τι τις δώσουμε, απλά οι συναρτήσεις έχουν πάντα δικό τους σωρό, πάντως και εδώ σε έναν προσωρινό θα περαστεί το 10, και επειδή οι συναρτήσεις έχουν νέο σωρό, αυτός θα γίνει ο νέος σωρός, θα εκτελεστεί η βήτα και θα αφήσει στο σωρό της ΑΛΦΑ την τιμή και μετά θα τρέξει ο κώδικας της ΑΛΦΑ. Όλα αυτά μπορεί περίπου να γίνονται στην VB6, αλλά αυτό που δεν γίνεται είναι ότι ο σωρός μπορεί να έχει και άλλες τιμές πριν την κλήση, και επίσης να επιστραφούν τιμές σε αυτόν, δηλαδή με την επιστροφή της ΑΛΦΑ να βάλει στο σωρό, στην κεφαλή ή στην ουρά (ο σωρός τιμών διαβάζεται πάντα από την κεφαλή, αλλά παίρνει τιμές στην κεφαλή ή στην ουρά). Έτσι ένα τμήμα της Μ2000 μπορεί να γυρίζει πολλαπλές τιμές. Κάτι τέτοιο δεν το κάνει η Vb6, γιατί απλά εκεί καθορίζουμε τι γυρνάμε εκ των προτέρων. Στη Μ2000 τα τμήματα είναι μεταφορείς/επεξεργαστές δεδομένων.

 

Δεν μπορούμε λοιπόν να πούμε ότι η Vb6 έχει κάτι αντίστοιχο με το τμήμα της Μ2000. Ένα τμήμα στη Μ2000 μπορεί να έχει μέρη του που να τρέχουν σε ένα ή πολλαπλά νήματα. Και πάλι εδώ η VB6 δεν έχει κάτι να δείξει! Επίσης ένα τμήμα εκτός από άλλα τμήματα και συναρτήσεις και νήματα μπορεί να έχει ρουτίνες. Οι ρουτίνες είναι μέρη του κώδικα του τμήματος που μπορούν να τρέξουν κατ' απαίτηση και έχουν αναδρομή. Σε μια ρουτίνα βλέπουμε ότι έχει το τμήμα, άρα και όλες τις ρουτίνες. Ότι νέο φτιάξουμε σε μια ρουτίνα χάνεται. Αυτές είναι οι ρουτίνες με την δομή ΡΟΥΤΙΝΑ ...ΤΕΛΟΣ ΡΟΥΤΙΝΑΣ και πάνε πάντα στο τέλος και το όνομα έχει σημασία να είναι ακριβώς το ίδιο στην κλήση (μικρά-μεγάλα-τόνοι είναι σημαντικά). Οι κλήσεις συναρτήσεων και τμημάτων γίνονται βάσει λίστας, ενώ οι κλήσεις ρουτινών με αναζήτηση στον κώδικα, πάντα από το τέλος. Δεν μπορούμε να καλέσουν τμήμα που δεν ορίσαμε (που δεν γράφτηκε στη λίστα) αλλά καλούμε ρουτίνα αρκεί να είναι στο κώδικα απ' όπου φορτώθηκε το τμήμα για εκτέλεση, ή στο πατρικό αυτού (μπορούμε ένα ορισμό ρουτίνας να τον χρησιμοποιούν "Αδέλφια" τμήματα, αλλά σε κάθε περίπτωση είναι σαν να βρίσκεται η ρουτίνα στο χώρο του καθενός, γιατί εκτελείται στο όνομα του τμήματος, το οποίο είναι και το namespace ή όνομα χώρου.

 

Μια διαφοροποίηση της VB6 με την Μ2000 είναι το namespace. Στη VB6 υπάρχει μεν σε επίπεδο Module και κλάσης, αλλά επειδή δεν έχει φωλιασμένα τμήματα πρακτικά δεν κερδίζει κάτι. Στη Μ2000 ένα τμήμα μπορεί να αλλάξει όνομα και ταυτόχρονα να δημιουργήσει νέο σετ μεταβλητών.. Το όνομα το παλιό μπορεί να το γράψει σε μια στατική μεταβλητή. Η στατική μεταβλητή δεν έχει σχέση με το όνομα του τμήματος αλλά με το αντικείμενο εκτέλεσης. Δηλαδή  αν από το Β εκτελέσουμε δέκα φορές το Α τότε θα έρχεται πάντα το ίδιο αντικείμενο εκτέλεσης και θα παίρνει η Α την ίδια στατική. Αν την Α την καλή η Κ τότε θα έχει μια άλλη στατική σχετική με το αντικείμενο του Κ. Είναι προφανές ότι αν ένα Α φαίνεται και στο Β και στο Κ είναι γενικό! Υπάρχει όμως μια περίπτωση που δεν χρειάζεται να είναι. Αν ένα Β έχει ένα μέρος κώδικα ως νήμα και αυτό το καλέσει ως νήμα δέκα φορές τότε κάθε φορά που το νήμα θα καλεί το Α θα το καλεί μεν ως Β αλλά με ξεχωριστό αντικείμενο εκτέλεσης. Τα νήματα στην Μ2000 έχουν το όνομα χώρου του τμήματος που ανήκουν, βλέπουν τις ίδιες μεταβλητές και τα τμήματα ή συναρτήσεις που έχει αυτό, αλλά έχουν δικό τους σωρό και δικές τους στατικές γιατί βρίσκονται σε δικό τους αντικείμενο εκτέλεσης.

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

Π.χ. Αν έχω ένα τμήμα που σχεδιάζει ένα κύκλο και το καλέσω από ένα μπλοκ κώδικα που όρισα επίπεδο τη φόρμα 1 ο κύκλος θα βγει στην φόρμα 1. Δεν χρειάζεται να περάσω "παράμετρο" για την φόρμα, θα περαστεί αυτόματα, αφού το τμήμα κληρονομεί στοιχεία από το πατρικό αντικείμενο. Μπορώ να έχω 30 νήματα (για ένα γράφτηκε ο κώδικας) σε ένα τμήμα και το κάθε νήμα να το δημιούργησα σε ένα μπλοκ Επίπεδο Φόρμα1(ν) { } όπου το ν έπαιξε για 30 νούμερα, και έτσι το κάθε νήμα δημιουργήθηκε στον ίδιο χώρο ονόματος αλλά με διαφορετικό αντικείμενο , εδώ διαφορετικό παράθυρο.

Τα νήματα όπως και οι φόρμες..θα "πεθάνουν" με το που θα τερματίσει αυτό. Μέχρι τότε θα έχουν παίξει άλλα τμήματα, συναρτήσεις και ίσως μερικά τμήματα εμφανίσουν και αυτά παράθυρα.. Τα νήματα θα συνεχίσουν να τρέχουν στο πατρικό (εδώ υπάρχει το unsafe των νημάτων...επειδή μπορούν να δημιουργούν μεταβλητές χωρίς να τις σβήνουν. Ο λόγος που το επιτρέπω αυτό είναι το σινιάλο! Θα μπορούσε κανείς να δημιουργήσει μια γενική μεταβλητή σε νήμα που τρέχει στο πατρικό και θα είναι ορατή και παρακάτω, αρκεί το "παρακάτω" να τρέχει και αυτό. Όταν το "παρακάτω" τερματίσει τότε σβήνει και την γενική, γιατί σβήνονται βάσει σημείου "εισόδου" και η είσοδος έγινε με ν μεταβλητές όχι ν+1. Παρόλο που έχουμε νήματα στην Μ2000, οι μεταβλητές-πίνακες δημιουργούνται σε μια διάταξη στοίβας, και χάνεται πρώτη η τελευταία που δημιουργείται. Από το κανόνα βγαίνουν εκτός οι στατικές (δεν υπάρχουν πίνακες σε αυτές), που κρατούνται εκτός ονόματος χώρου, και ότι κρατάνε τα κλειστά αντικείμενα, που επίσης και αυτά είναι εκτός ονόματος χώρου.

 

Από την απλούστευση της VB6 ότι έχουμε ρουτίνες-συναρτήσεις και κλάσεις και φόρμες (ειδικές κλάσεις), πάμε στην Μ2000 όπου υπάρχει η έννοια του τμήματος-προγράμματος. Αυτό τα έχει όλα. Μπορεί να δέχεται αντικείμενα και να δίνει, να δημιουργεί αντικείμενα, να φτιάχνει φόρμες, να έχει έξοδο όπου θέλει, ή να τρέχει στην έξοδο που εμείς ορίζουμε από άλλο τμήμα. Για να κάνεις κάτι τέτοιο στην VB6 πρέπει σε κάθε ρουτίνα να βάλεις και ένα αντικείμενο "αγκαζέ". Αυτό κάνει η Μ2000 εσωτερικά.

 

Για όλα τα παραπάνω με βεβαιότητα μπορούμε να πούμε ότι δεεν έχουμε wrapper: Η χρήση δομών-αντικειμένων στη Μ2000 με ξεχωριστό τρόπο, αποτελεί άλλη επινόηση, ένα αποτέλεσμα που δεν αποδίδεται από την VB6 χωρίς να γράψεις πάλι το κώδικα που έχει η M2000 σε VB6. Αν η VB6 είχε τις επινοήσεις της Μ2000  τότε θα λέγαμε ότι έχουμε wrapper.

 

Να αναφέρω εδώ μια ακόμα επινόηση, το ανοικτό αντικείμενο. Έχω καταλήξει σε ένα γρήγορο ορισμό: Ανοικτό αντικείμενο τύπου ομάδα είναι μια επώνυμη λίστα μελών, που μπορεί να είναι τμήματα, συναρτήσεις, μεταβλητές - και λάμδα- και πίνακες, καθώς και άλλα ανοικτά αντικείμενα τύπου ομάδα. Το ανοικτό αντικείμενο δεν έχει στο χώρο κάποιο μέλος, διατηρεί μόνο μια λίστα αναφοράς. Τα τμήματα και οι συναρτήσεις έχουν μια ειδική αναφορά στο αντικείμενο που ανήκουν ώστε να μπορούν να καλούν τμήματα και νήματα και να βλέπουν δημόσια και ιδιωτικά μέλη. Τα ιδιωτικά μέλη και αυτά είναι "ελεύθερα" αλλά δεν βρίσκονται χωρίς την ειδική αναφορά. Κλειστό αντικείμενο είναι το αντικείμενο που δεν έχει πια μια λίστα αναφορών αλλά περιεχόμενο με όλα τα μέλη και είναι ανώνυμο, δεν έχει όνομα. Τα κλειστά αντικείμενα μπορεί να είναι σε πίνακες, στο σωρό τιμών ή στην επιστροφή τιμής από συνάρτηση.

Περιπτώσεις:

1. Αντιγραφή Αντικειμένου σε νέο όνομα

Αν το Α είναι αντικείμενο (άρα ανοικτό, αφού έχει όνομα) και το Β είναι νέο όνομα τότε αυτό:

Β=Α

θα κάνει το εξής: Θα βγεί ένα αντίγραφο του Α ως κλειστό αντικείμενο, θα επιστραφεί από το Α στο σύστημα παραστάσεων και θα ανοίξει ως Β, δηλαδή το Β θα γίνει ανοικτό αντικείμενο και τα μέλη του κλειστού αντικειμένου θα πάρουν όνομα και φυσική παρουσία. Θα έχουμε ένα γνήσιο αντίγραφο του Α με Deep Copy. (δεν έχει shallow copy η Μ2000).

το ίδιο θα γίνει και με αυτό, απλά εδώ η συνάρτηση δίνει το κλειστό αντικείμενο.

Β=Κλαση1()

 

Το ίδιο θα γίνει και με αυτό Διάβασε Β αν το Β είναι νέο όνομα και στο σωρό έχουμε κλειστό αντικείμενο.

 

2. Συγχώνευση Αντικειμένου σε Αντικείμενο

Β=Α

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

ισχύει επίσης αυτό:

Β=Κλάση1()

και αυτό Διάβασε Β

 

3. Αντικατάσταση κλειστού αντικειμένου από κλειστό αντικείμενο

Πίνακας Α(10)

Α(3)=Β

Α(3)=Γ

Αν τα Β και Γ είναι αντικείμενα τότε στην περίπτωση του Α(3)=Β ετοιμάζεται ένα κλειστό αντικείμενο, αντίγραφο του Β και μπαίνει ως έχει στο Α(3). Στην αμέσως επόμενη γραμμή, ετοιμάζεται ένα κλειστό αντικείμενο από το Γ και μπαίνει στο Α(3), το παλιό χάνεται..(δεν υπάρχει κανείς που να το κρατάει). Εδώ έχουμε περιγραφικά το εξής, σε ψευδοκώδικα., που μοιάζει περισσότερο με VB6

Set A(3)= Γ.closedGroup

Μπορούμε όμως να το κάνουμε ανοικτό για λίγο:

Για Α(3) {

    Αυτό=Β

}

Το Αυτό είναι το Α(3) ως ανοικτό αντικείμενο. Δηλαδή πρόσκαιρα στο Α(3)  δόθηκε όνομα το οποίο είναι κρυφό και αντί αυτού χρησιμοποιούμε το Αυτό. Κάνουμε ότι θέλουμε με αυτό και μετά το μπλοκ κλείνει το αντικείμενο και μπαίνει στο Α(3). Τώρα με αυτόν τον τρόπο έχουμε όλα τα καλά του ανοικτού αντικειμένου, όπως και το πέρασμα με αναφορά, αυτού ή μέλος του:

Για Α(3) {

    Τμήμ001 &Αυτό

    Τμήμ002 &Αυτό.Χ

}

Στη δεύτερη περίπτωση περνάμε μόνο το Χ με αναφορά (μια ιδιότητα του Α(3))

Αυτό σίγουρα δεν γίνεται στην Vb6 και παίζει αν γίνεται αλλού...με απλό τρόπο!

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ακόμα κατανοεί πως δουλεύουν τα modals, αφού έκανε τα lambda σε 2 ημέρες. Βάλε και μία να ξεκουραστεί, ε.., μέσα Μαΐου θα είναι έτοιμο full stack σε Μ2000

 

Τι δουλεια εχεις εσυ εδω μέσα? πάλι μπηκες να κράξεις?

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Μπράβο Μ2000...!

 

Απέκτησες και σκυλάκι! :D

 

Προσεξε γιατι το σκυλάκι δαγκώνει ;)

 

με τους ενοχλητικους δεν τα πάει καλά.

 

Επισης σε λιγο καιρο θα προσλάβουμε και ασφάλεια για το θρεντάκι. Ιδιωτική ασφάλεια οποιος μπαινει να κράξει και να ενοχλησει χωρις λογο οπως εσυ καλη ώρα θα φευγει κερασμένος. Αμα δεν σ αρεσει μην μπαινεις καθολου στο θρεντ. ;)

 

Εσυ ειχες πει οτι δεν θα ασχοληθεις ξανά. Ωραια κανε μας τη χαρη και μην ασχολεισαι τοτε.Πηγαινε αλλου να κανεις τον διδάκτορα.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Αναθεώρηση 224.

Ασχολήθηκα με την βελτίωση του κώδικα. Τώρα τρέχει καλά και σε Linux.

Κλήση με αναδρομή σε ρουτίνα (50 χιλιάδες κλήσεις)

 

Recursion.limit 50000
Profiler
rec(50000)
Print Timecount

Sub rec(x)
Print x
If x>1 Then rec(x-1)
End Sub

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Έκδοση 8.1

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

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ανέβασα μια ανάρτηση για τους jagged arrays Link.png Site: εδώ

 

π.χ. εδώ:

A(0)(0)(5,1)=500

σημαίνει ότι στο Α(0) υπάρχει πίνακας και εκεί στο πρώτο στοιχείο (0) υπάρχει άλλος πίνακας δυο διαστάσεων και θα γράψουμε στο (5,1) το νούμερο 500.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Αυτό δεν είναι jagged array αλλά 3D array.

 

Επίσης, ποια είναι η συνολική διάσταση του Α(0,0) στοιχείου; Δηλαδή, το (5,1) στο Α(0,0) έγινε 500. Το (5,5) (π.χ.) τι τιμή έχει;

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημοσ. (επεξεργασμένο)

Απλά είδες για ένα στοιχείο το Α(0).

 

Δες το παράδειγμα εδώ: Φτιάχνουμε πίνακες με συναρτήσεις, στο μέγεθος που θέλουμε. (Στους αριθμητικούς πίνακες η Μ2000 μπορεί να βάζει ομάδες, συναρτήσεις λάμδα και από την 8.1 πίνακες. Δεν είναι μόνο το πώς μπαίνει κάτι αλλά και πώς δουλεύει, το interface δηλαδή. Εδώ πρέπει να έχουμε ξεκαθαρίσει ότι σε αριθμητικό πίνακα θα βάλουμε έναν αριθμητικό.

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

Μια συνάρτηση επιστρέφει τιμή με το =. Στην ουσία ο εκτιμητής εκφράσεων (πες τον expression evaluator) αν δει ότι έχει αποτέλεσμα αντικείμενο τότε βάζει μηδέν για τιμή και το αντικείμενο με αναφορά χωριστά. Το τι θα γίνει το αντικείμενο το καθορίζει η αριστερή πλευρά της εκχώρησης. (αυτή την απλή ιδέα που περιέγραψα, έκανα χρόνια για να την καταλάβω, και να βάλω αντικείμενα ως επιστροφή σε evaluator, αλλά εδώ φαίνεται απλό).

Αυτό λοιπόν που έκανα είναι ότι το Α(0) αν το συνεχίσω με Α(0)() ο διερμηνευτής θα ψάξει για πίνακα ή για λάμδα (μπορεί να μπει και συνάρτηση λάμδα στο πίνακα), και θα "ακολουθήσει" ανάλογα.

 

Μπορούν να γραφτούν "μακρινάρια" όπως Α(0)(5,4)(2)(4) γιατί κάθε φορά που βρίσκει o διερμηνευτής νέο πίνακα κάνει μετάθεση του δείκτη..π.χ. ο δείκτης εσωτερικά στον διερμηνευτή είναι το pppp που είναι κλάσης mArray, έτσι κάθε φορά γίνεται νέο set pppp=pppp.item(v) όπου το pppp.item(v) είναι πίνακας. Η Vb6 έχει πίνακες τύπου Variant, όπου μπορούμε να γράψουμε ότι θέλουμε, από τιμή απλή μέχρι και αντικείμενα. Το item(v) είναι ιδιότητα του mArray.

 

Ας πούμε ότι στον Α(0) έχουμε βάλει το dimany(200), ένα πίνακα 200 στοιχείων

Αν κάνουμε το Dim B() : Β()=Α() θα πάρουμε αντίγραφο του Α() στο Β() αλλά με shallow copy. Αν θέλουμε ο πίνακας στο Β(0) να μην δείχνει τον Α(0) τότε με Β(0)=Β(0) κάνουμε shallow copy τον ίδιο πίνακα. με συνέπεια το B(0) να δείχνει σε νέο πίνακα και όχι αυτόν του Α(0).

 

 

\\ M2000 Jagged array

Dim a(3)

Function dimany {

dim a(number)

=a()

}

Function dim2any {

dim a(number, number)

=a()

}

A(0)=dimany(10)

A(1)=dimany(4)

A(2)=dimany(2)

A(0)(8)=100

Print A(0)(8)

A(1)(2)=101

Print A(1)(2)

A(2)(0)=102

Print A(2)(0)

A(0)(0)=dim2any(30,2)

A(0)(0)(5,1)=500

Print A(0)(0)(5,1)

For i=1 to Dimension(A(0)(0)())

Print i, Dimension(A(0)(0)(),i) ' 30..2

Next i

Print Dimension(A(0)(),1) '10

Print Dimension(A(),1) '3

 

 

Να και ένα ακόμα:

Το group είναι ανοικτό αντικείμενο. Ανοικτό σημαίνει "επώνυμο", και ότι όλα τα στοιχεία του είναι γνωστά στο διερμηνευτή. Τα κλειστά αντικείμενα είναι αυτά που βρίσκονται σε πίνακες. Δεν τα γνωρίζει ο διερμηνευτής, είναι σαν να μην υπάρχουν, εκτός και αν πάμε να τα διαβάσουμε, οπότε πρόσκαιρα ανοίγουν, δουλεύουν και κλείνουν. Ουσιαστικά το άνοιγμα σημαίνει ότι ο διερμηνευτής τους δίνει όνομα. Μόνο με όνομα χειρίζεται αντικείμενα! Μπορούμε να έχουμε ιδιωτικά και δημόσια μέλη σε μια ομάδα (group) αλλά αν δεν δηλώσουμε με ετικέτα τι να λογαριάσει από κει και κάτω, τότε θεωρεί ότι είναι δημόσιο. Εδώ ο πίνακας b(10) είναι δημόσιο μέλος της ομάδας alfa (οι ομάδες είναι ανοικτά αντικείμενα και για άλλο λόγο, μπορούν να πάρουν μέλη στη πορεία, αλλά δεν μπορούμε να αφαιρέσουμε μέλη). Μια ομάδα μπορεί να έχει υποομάδες και μπορεί να καλεί συναρτήσεις (από τμήματά της, ή συναρτήσεις της) και να περνάει την αναφορά σε αυτήν με το &This ή &Αυτό.

 

Το beta=alfa κάνει deep copy το alfa στο beta. Ισχύει και εδώ ότι η αντιγραφή στους πίνακες γίνεται στο πρώτο επίπεδο. Όμως αν έχουμε ομάδες στην ομάδα θα γίνουν κανονικά αντιγραφές.

Η τελευταία γραμμή του παραδείγματος έχει αυτό:

Print alfa.b(1).b(4)(1,2)()

εδώ έχουμε αντικείμενο alfa, πίνακας σε αυτό b, στο στοιχείο 1 έχουμε ένα άλλο αντικείμενο (δεν έχει τύπους αντικειμένων η Μ2000), όπου και αυτό έχει ένα πίνακα b, στο στοιχείο 4 έχουμε ένα δυο διαστάσεων πίνακα και στο στοιχείο 1,2 σε αυτόν έχουμε μια λάμδα συνάρτηση η οποία εκτελείται και αλλάζει την τιμή μιας Ν δική της. Την επόμενη φορά θα πάρουμε το επόμενο Ν (το N+1, εδώ γίνεται με το N++ στην λάμδα)

 

 

group alfa {

dim b(10)

}

alfa.b(3)=100

beta=alfa

alfa.b(3)=10

Print beta.b(3)

alfa.b(1)=beta \\αντίγραφο του beta στο alfa.b(1)

Print alfa.b(1).b(3) \\100

beta.b(3)+=100

Print beta.b(3)

Print alfa.b(1).b(3) \\100

\\\ μπλοκ για προσωρινή δημιουργία

\\ ο πίνακας tmp θα διαγραφεί

\\ θα μείνει αντίγραφο στο alfa.b(1).b(4)

For This {

dim tmp(4,3)=1234

alfa.b(1).b(4)=tmp()

}

\\ ανοίγει πίνακα b(1)

\\ βρίσκει αντικείμενο στο b(1)

\\ το οποίο έχει και αυτό ένα πίνακα b

\\ όπου στο 4 έχει έναν πίνακα δυο διαστάσεων 4x3

\\ και αυξάνει κατά ένα

alfa.b(1).b(4)(2,2)++

Print alfa.b(1).b(4)(2,2) \\1235

bb=lambda N=1 ->{=N : N++}

Print bb() ' 1

Print bb() ' 2

alfa.b(1).b(4)(1,2)=bb

Print alfa.b(1).b(4)(1,2)() ' τυπώνει 3

Print bb() ' τυπώνει 3 γιατί το προηγούμενο ήταν αντίγραφο, και αντιγράφεται όλη η κατάσταση της λάμδα

For i=1 to 5 {print bb()} ' 4,5,6,7,8

Μ=alfa.b(1).b(4)(1,2) '' δημιουργεί την Μ λάμδα

For i=1 to 5 {print Μ()} ' 4,5,6,7,8

Print alfa.b(1).b(4)(1,2)() ' τυπώνει 4

 

Μια ακόμα προσθήκη:

Πίνακες σε αντικείμενα, με ιεραρχία (φωλιασμένα αντικείμενα). Το ανοικτό αντικείμενο alfa, έχει επίσης ένα ανοικτό beta. (θα μπορούσε στους πίνακες να έχει κλειστά αντικείμενα). Εδώ όμως θα φτιάξουμε έναν πίνακα Α() που θα έχει δέκα αντικείμενα alfa, και το καθένα θα έχει τους δικούς του πίνακες (Από δυο το καθένα, τον .a() και τον .beta.a()).

Η επανάληψη με το For (υπάρχει σε For Next και στο γρηγορότερο For {} δηλαδή με μπλοκ) δείχνει ότι όλοι οι πίνακες είναι διαφορετικοί.

 

 

Group alfa {

dim a(10)=1

Group beta {

dim a(20,30)=5

}

}

Print alfa.beta.a(2,2)

Dim A(10)=alfa \\ κάθε πίνακας έχει ένα αντίγραφο το alfa με deep copy

A(1).beta.a(2,2)++

Print A(1).beta.a(2,2)

For i=0 to 9

A(i).beta.a(0,2)+=i

Print A(i).beta.a(0,2)

Next i

Print A(5).beta.a(0,2)-A(2).beta.a(0,2) \\ 3

A(5).a(1)+=10

Print A(5).a(1)-A(2).a(1) \\ 10

Επεξ/σία από M2000
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Μια επίδειξη των GUI χαρακτηριστικών της Μ2000 σε μια εφαρμογή γραμμένη σε Μ2000 (ένα αρχείο text σε Utf8 με κατάληξη gsb)

Τρέχει σε έκδοση 8.1 αναθεώρηση 9.

 

 

Ανοίγω ένα αρχείο με >30Κ γραμμές της VB6 τις οποίες χρωματίζει το στοιχείο ελέγχου on the fly, τμηματικά όπως το βλέπουμε. Επίσης αρχικά ανοίγει με αναδίπλωση παραγράφων, και αυτό γίνεται στο φόρτωμα και σε resize, καθώς και σε μετάβαση από "χωρίς αναδίπλωση" σε αναδίπλωση.

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

Επίσης δείχνει πώς επιλέγοντας μια λέξη (εδώ το Set) μπορούμε να μετακινηθούμε στην ίδια πάνω ή κάτω (με F2 και F3), ή να αλλάξουμε μεγάλα-μικρά π.χ. από Set σε set και αυτό να γίνει για όλο το κείμενο άμεσα με F4. Βλέπουμε ακόμα πως ορίζουμε σελιδοδείκτες (στη πράξη δείχνουν σε παράγραφο και θέση σε παράγραφο βάσει του εσωτερικού αριθμού και όχι της θέσης της παραγράφου), με τα F6, F7, F8.

Με F9 παίρνουμε μια μέτρηση λέξεων, με F10 γυρνάμε σε προβολή μη εκτυπώσιμων χαρακτήρων, με F11 κάνουμε εναλλαγή από χρωματισμένο σε μη χρωματισμένο κείμενο.

(Το F5 δεν εμφανίζεται εδώ αλλά είναι η αλλαγή λέξης με άλλη λέξη σε όλο το κείμενο, ανοίγει παράθυρο που ζητάει το όνομα για την αλλαγή).

Επειδή το πλήκτρο tab χρησιμοποιείται για αλλαγή στοιχείων ελέγχου (π.χ. από το editbox πάμε στο combo που παίζει το ρόλο του μενού), για να βάλουμε πρόσθετα διαστήματα αριστερά ή χρησιμοποιούμε το μενού Edit,  ή πατάμε και το Ctrl μαζί. Έτσι Tab+Ctrl βάζει διαστήματα σε μια ή περισσότερες παραγράφους και το Tab+ctrl+shift βγάζει. Το Tab+Ctrl έχει άλλη λειτουργία όταν δεν το δέχεται το EditBox, να αλλάζει παράθυρα στην εφαρμογή. Δηλαδή σε άλλο πρόγραμμα με πολλά παράθυρα ανοικτά (που δεν έχουν ακινητοποιηθεί από modal παράθυρο), μπορούμε να χρησιμοποιούμε το πληκτρολόγιο για να κάνουμε κάθε εργασία (που θα κάναμε με το ποντίκι). Αυτό φαίνεται φυσικό για τα παράθυρα. αλλά εδώ έχουμε παράθυρα της Μ2000 και αυτή η λειτουργία έπρεπε να γραφτεί.

 

Δείτε επίσης ότι ανοίγω δυο ειδών αρχεία, τα .bas και τα .txt, και όταν έχω τα δεύτερα δεν χρωματίζονται, όπως είναι φυσικό. Επίσης ανοίγω ένα txt με ρώσικα και γεωργιανά.

 

Γενικά τα παράθυρα στην Μ2000 έχουν ως βάση μια φόρμα της VB6 GuiM2000 και πάνω σε αυτήν μπαίνουν δυναμικά άλλα στοιχεία. Το ενδιαφέρον εδώ είναι ότι τα στοιχεία αυτά είναι όλα ίδια. Είναι δηλαδή ένα User Control. Η παραλλαγή του τύπου γίνεται από την Μ2000 με εφαρμογή μιας ενδιάμεσης κλάσης, που δεν είναι φόρμα, ούτε στοιχείο ελέγχου, αλλά είναι αυτή που διαχειρίζεται το στοιχείο, λαμβάνοντας μηνύματα και στέλνοντάς τα μέσω της φόρμας, στο τμήμα που δημιούργησε τη φόρμα.

 

 

 

MODULE A {\\ notepad
Clear \\ Clear all variables/objects
Flush \\ Empty the stack
Title$="M2000 Pad"
typ$="txt"
Dir User

Declare NotePad Form
Declare Pad EditBox Form NotePad
Declare Inform1 Button Form NotePad
Method Inform1, "Colors", 15, #FFA000
With Inform1, "Locked", true
Declare File1 Combobox Form NotePad
Declare Edit1 Combobox Form NotePad
Declare Help1 Combobox Form NotePad
With File1,"label","File", "listtext" As list$, "list" As list$() '
With Edit1,"label","Edit",  "Mark", Color(255,100,0)
With Help1,"label","Help",  "Mark", Color(255,100,0)
With NotePad, "Title" As Caption$, "Visible" As Visible, "TitleHeight" As tHeight, "Sizable", True
With Pad, "Text" As Pad.Text$, "ShowAlways", True,"NoColor", True,"SelLength" as SelLength
Def TitleStr$(a$)=ucase$(left$(a$,1))+mid$(a$,2)
Filename$=Dir$+"Untitled.txt"
Caption$=TitleStr$(File.Name$(Filename$)) +" - M2000 Pad"
Method NotePad,"move", 2000, 4000, 8000, 4000
Layer NotePad {Cls #FFA000}
With File1,"MenuStyle", True, "MenuWidth", 3000
With Edit1,"MenuStyle", True, "MenuWidth", 3000,"menuEnabled" as Enabled()
With Help1,"MenuStyle", True, "MenuWidth", 3000
With File1, "MenuEnabled" As mEnable()
For This {
      mi$="MenuItem"  \\ is a temporary variable only for For This Block
      With File1, "MenuGroup","This"
      Method File1, mi$,"Open",True
      Method File1, mi$,"Save",True
      Method File1, mi$,""    \\  only  a line here
      Method File1,"MenuRadio","txt files",True,True
      Method File1,"MenuRadio","bas files",True,False
      
      Method File1, mi$,""
      Method File1, mi$,"Close",True
      Method File1, mi$,""
      Method File1, mi$,"Quit",True
      
      With Edit1, "MenuGroup","This"
      Method Edit1, mi$,"Cut",False
      Method Edit1, mi$,"Copy",False
      Method Edit1, mi$,"Paste",True
      Method Edit1, mi$,""
      Method Edit1, mi$,"Less Indent",True
      Method Edit1, mi$,"More Indent",True
      With Help1, "MenuGroup","This"
}

Document BackUp$="Write something..."
Pad.Text$=BackUp$
Function NotePad.Unload {
      Read New &Ok
      After 30 {call local File1.DblClick(8) }
      Ok=True

}
Function Notepad.Resize {
      Layer NotePad { Cls Color(255, 160, 0) ,0}
      With NotePad, "Width" As NP.Width, "Height" As NP.Height, "TitleHeight" As tHeight
      tHeight1=theight*2
      Method File1,"move", twipsX*2, tHeight, twipsX*80, tHeight
      Method Edit1,"move", twipsX*2+twipsX*80, tHeight, twipsX*80, tHeight
      Method Help1,"move", twipsX*2+twipsX*160, tHeight, twipsX*80, tHeight
      Method Inform1,"move", twipsX*2+twipsX*240, tHeight, twipsX*160, tHeight
      If NP.height>1000 Then {
            Method Pad,"move", twipsX*2, tHeight1, NP.Width-twipsX*5, NP.Height-tHeight1-twipsx*3
            With Pad, "NoWrap" As NoWrap
            If Not NoWrap Then Method Pad,"Resize"
      }
}
Function Edit1.OpenMenu {
            Local X
            X=SelLength>0
            Enabled(0)=X
            Enabled(1)=X
}

Function Edit1.DblClick {
      Read Local Edit1index
      Select Case Edit1index
      Case 0
            {
            Method Pad,"mn1sub"
            Method Pad,"Resize"
            }
      Case 1
            Method Pad,"mn2sub"
      Case 2
            {
                 Method Pad, "mn3sub"
                 Method Pad,"GetFocus"
                 Method Pad,"Resize"
           }
        Case 4
           {
                  Method Pad,"PressKey", 9, 1
            }
        Case 5
           {
                  Method Pad,"PressKey", 9, 0
            }
      End Select

}
Function Pad.Inform {
      Read New L, P
      With Inform1, "Caption", format$("{0}-{1}", L,P)
      Method Pad,"Show"
}
Function Pad.PopUp {
      Read Local X, Y
      Method Pad,"PopUpMenu", "",X , Y
}
Function File1.MenuChecked {
Read New RadioIndex \\ 3 or 4
If RadioIndex =3 then {
      After 30 { local a$="."+file.type$(Filename$), b$=File.name$(Filename$)
      Filename$=File.path$(Filename$)+Left$(B$,Len(B$)-Len(a$))+".txt"
      Caption$=TitleStr$(File.Name$(Filename$)) +" - M2000 Pad"
      typ$="txt"
      With Pad, "ColorCollection1", "","NoColor", True
      Method Pad, "Show"
      }
} else.if RadioIndex =4 then {
     After 30 { local a$="."+file.type$(Filename$), b$=File.name$(Filename$)
      Filename$=File.path$(Filename$)+Left$(B$,Len(B$)-Len(a$))+".bas"
      Caption$=TitleStr$(File.Name$(Filename$)) +" - M2000 Pad"
      typ$="bas"
      With Pad, "ColorCollection1", "|AND|OR|XOR|NOT|CLS|DEBUG.|PRINT|DECLARE|CONST|GOTO|DO|LOOP|WHILE|WEND|WITH|REFRESH|LET|GET|SET|DOEVENTS|SELECT|CASE|FALSE|TRUE|OPTION|EXPLICIT|LIB|DIM|REDIM|PUBLIC|PRIVATE|FUNCTION|SUB|IF|THEN|ELSE|ELSEIF|END|SELECT|FOR|NEXT|TO|AS|LONG|BOOLEAN|STRING|OBJECT|EXIT|BYVAL|NEW|LEFT$(|LEFT(|RIGHT$(|RIGHT(|MID$(|MID(|UBOUND(|LBOUND(|CSTR(|CDBL(|CLNG(|STR$(|STRING$(|INSTR(|ASC(|CHR(|CHR$(|COS(|SIN(|LOG(|RGB(|REPLACE(|","NoColor", False
      Method Pad, "ReColor"
      Method Pad, "Show"
      }
}

}
Function File1.DblClick {
\\ we use functions As subs here
\\ each function and each module have a name (define a namespace)
\\ but here real module name is the File1.DblClick() host module
\\ this is done because is a Gui Event Service Function
\\ and is call with Local tag (Call Local)
      Read New File1index
      Local cont, cont2, f$, NL$={
      }
      File1index++
      \\ Because we want some jumps..we use  On Goto
      \\ on Goto need here a block
      {
      On File1index Goto Open1, Save1, ExitNow, ExitNow, ExitNow, ExitNow, Save2, ExitNow, Unload
Exitnow:
      Exit
Open1:
      If Pad.Text$<>BackUp$ Then {
            If Ask("Save Changes first?",Title$, "Yes","No")=1 Then Goto Save1
      }
     Layer NotePad {
           Open.file filename$,,"Load Text ("+typ$+") File",typ$
     }
     Method Pad,"GetFocus"
     Read f$
     If f$<>"" Then {
           Filename$=f$
           If exist(F$) then {
           Clear BackUp$
           Load.Doc BackUp$, f$
           
           Caption$=TitleStr$(File.Name$(Filename$)) +" - M2000 Pad"
           Pad.Text$=BackUp$
           } else Pad.text$="": Clear BackUp$
           Method Pad, "ReColor"
      }
      Exit
Save1:
      Layer NotePad {
            Save.As Filename$,,"Save Text ("+typ$+") File",typ$
      }
      if not cont2 then Method Pad,"GetFocus"
      Read f$
      If f$="" Then Exit
      If lcase$(file.type$(f$))<>typ$ then f$=f$+"."+typ$
      If Exist(f$) Then If Ask(NL$+"Overwrite"+NL$+f$,Title$, "Yes","No")<>1 Then Exit
      Try ok {
        Clear BackUp$
        BackUp$=Pad.Text$
        Save.Doc BackUp$, f$
        filename$=f$
        Caption$=TitleStr$(File.Name$(Filename$)) +" - M2000 Pad"
      }
     If ok else beep
     If not cont then Exit
Save2:
      cont=True
      If Pad.Text$<>BackUp$ Then {
            If Ask("Save Changes?",Title$, "Yes","No")=1 Then Goto Save1
      }
      Clear BackUp$
      Pad.Text$=""
      If Cont2 then {
            Method NotePad, "CloseNow"
      } Else {
            FileName$=Dir$+"Untitled."+typ$
            Caption$=TitleStr$(File.Name$(Filename$)) +" - M2000 Pad"
            Method Pad, "Resize"
      }
      Exit
Unload:
      Cont2=True : Goto Save2
      }
}
Function Help1.OpenMenu {
      Local A, info$
      Info$={
            This is an example
            of a notepad
            written for M2000 Environment
            use F1 to change wrap
            }
      A=Ask(info$,Title$,"","")
      Method Pad, "GetFocus"

}
Call Local Notepad.Resize()
\\ open As moda
Title Title$, 0
After 100 {Title Title$}
Method NotePad,"Show" , 1
Declare Pad Nothing
Declare NotePad Nothing
Print "Done"

}
A: end

 

 

 

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • 2 εβδομάδες αργότερα...

Αναθεώρηση 18, έκδοση 8.1

Μπήκαν οι Διαρθρώσεις (Buffers) που λέγονται έτσι γιατί είναι διαρθρώσεις μνήμες με δομές. Μπορούν να περαστούν σε dll, υποστηρίζουν union σε offsets, και casting.

Link.png Site: Δiάρθρωσηή Buffer

(πέντε μέρες δουλειά).

Έχω βάλει και μια Execute Code buffer1, αλλά προς το παρόν μόνο το 0xC έχω βάλει που επιστρέφει τη κλήση. Σκοπός μου είναι να βάλω και Assembly 8086 στη Μ2000 και έχει δυσκολέψει πολύ το πράγμα.

Στις Διαρθρώσεις (buffers) έχω βάλει αρκετές "ασφάλειες" ώστε αν κάνει λάθος ο προγραμματιστής να μην έχουμε κρέμασμα (δεν αφήνω να γραφτεί κάτι απ έξω.

Όμως το Execute Code είναι εντελώς έξω από κάθε "ασφάλεια"!

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

Ενώ δουλεύει εσωτερικά με HeapAlloc, δεν χρειάζεται να κάνουμε κάτι  για free, γίνονται αυτόματα από τον διερμηνευτή, ακόμα και α κάνουμε λάθος, θα καθαρίσει! Μπορούμε να φτιάχνουμε buffers κενά ή ως έχουν, και επίσης έχουν και redim, χωρίς να σβήνουν τα δεδομένα. Μέχρι δυο βαθμούς offsets χειρίζονται αυτόματα (δυο μεγέθη χωριστά δηλαδή), μετά πρέπει να δίνουμε το υπολογισμένο offset. Οπουδήποτε όμως μπορούμε να γράψουμε κείμενο σε Ansi η σε Utf-16LE, και να διαβάσουμε, ενώ οι "διακριτές" τιμές είναι τέσσερις, byte, integer (2 bytes), long (4 bytes) τα οποία είναι unsign, και double (8 bytes). Ίσως βάλω και single (4 Bytes) και Currency (8 bytes). Δεν μπορούμε να γράψουμε αντικείμενα στους buffers. Το όνομα Διάρθρωση είναι ουσιαστικό, που σημαίνει αυτό που έχουμε στη μνήμη, μια διάρθρωση επιμέρους στοιχείων, που δηλώνουμε πχ. 

Διάρθρωση κενή άλφα ως ακέραιος * 1000

φτιάχνει 2000Bytes με 0 στο καθένα. και είναι ότι πρέπει για αλφαριθμητικό!

Δεύτερη εντολή δεν θα καθαρίσει όλο χώρο αλλά μόνο το νέο

Διάρθρωση κενή άλφα ως ακέραιος * 2000

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Επισκέπτης
Αυτό το θέμα είναι πλέον κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...