Τρίτη, 24 Απριλίου 2018

Αναθεώρηση 3, Έκδοση 9.3

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

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

Στο παράδειγμα η "πατάτα" έχει μόνο ένα μέλος το κ. Θα μπορούσε όμως να είχε πολλά!



\\ two kinds of pointers
\\ this is a named group, non movable,  and deleted at the exit of scope.
group potato {
      k=10
}
\\ m pointer point to named group
m->potato
Print m=>k
m=>k++
Print potato.k = m=>k ' true
m1=m ' this is a copy of pointer, so m1 points to potato too
m1=>k+=100
Print m1=>k = potato.k ' true
\\ we can use this pointer until original group get out of scope
\\ m get a pointer from a copy of group potato.
\\ a copy is a floating group, a nameless group, which can be  moved
m->(potato)
m=>k*=100
Print m=>k \\ 11100
\\ we can get a copy of the pointed group by m
\\ to a new named group, potato2
potato2=group(m)
Print potato2.k \\ 11100
b->m
Print b=>k =11100 ' true
\\ a pointer can get a new pointer
m->m1
Print m=>k = 111 ' true
\\ so now b points to old m
Print b=>k= 11100 ' true
m1->potato2 ' true
Print potato2.k=11100 'true
Print m1=>k=potato2.k ' true
\\ change pointer b to point to new m
b->m
Print b=>k=111 ' true
\\ a pointer can use = to get a value from other pointer
b=m1
Print m=>k=111
Print b=>k=11100
\\ this is the null pointer
m->0
Print type$(m) ' it is a group, with no members
\\ we can check if member k exist
Print valid(m=>k)=false ' give true
\\ so now we change  the pointer
m->b
Print valid(m=>k)=true ' give true
\\ passing pointer by value (as pointer)
Module ByValue (x) {
      x=>k++
}
ByValue m
\\m has same pointer as before, so b points to m
Print m=>k=11101 ' true
Print b=>k=11101 ' true
Module ByRef (&x) {
     class NewX {
            k=20000
      }
      x->NewX()
}
ByRef &m
\\ m change pointer
\\ so b points to old m
Print m=>k=20000 ' true
Print b=>k=11101
Dim a(100)
\\ we can set pointers for groups to array items
a(3)->b
Print a(3)=>k ' 11101
a(3)=>k++
Print b=>k '11102
\\ as usual we can push a copy of potato to container a()
Print potato.k=111
a(4)=potato
\\ we can set pointer to groups in other array items
a(10)->a(4)
b->a(4)
potato.k=20
Print potato.k=20
Print a(10)=>k=20 ' false
\\ we can change a(4) without change any pointer to it
For a(4) {
      \ this is the a(4)
      this=potato
      \\ no use of =>
      \\ we can use a(4) inside for too
      Print .k=20, a(4)=>k=20 \\ true  true
}
\\ so now a(10) points to same a(4), but as a copy of potato;
Print a(10)=>k=20 ' true
\\ and b points to a(4) too
Print b=>k=20 ' true
\\ we can place pointers to groups in any container
\\ in each of the two kinds, but the non moveable has a risk
\\ to get out of scope.
Inventory banana= 1:=b
Print banana(1).k = 20 ' true
a(4)=>k+=30
Print banana(1).k = 50 ' true
banana(1).k+=50
Print a(10)=>k=100 ' true



Άλλο παράδειγμα με συνδεδεμένη λίστα. Η κλάση AnyName, δεν έχει το pnext. Χρησιμοποιούμε την InsertPnext για να ετοιμάσουμε το τελικό πρώτυπο για τη συνδεδεμένη λίστα.

flush
class AnyName {
      name$
class:
      module AnyName {
            Read .name$
      }
}
Class Null {
      IsNull=true
}
Class InsertPnext {
      Group pnext
      IsNull=false
      class:
            module InsertPnext {
                  Read this
                  .pnext->Null()
             }      
}
\ Linked List
a1->InsertPnext(AnyName("George"))
a1=>pnext->InsertPnext(AnyName("Peter"))


Function Count(x as pointer) {
            Count=0
            While not x=>isNull {
            Count++
            x=x=>pnext
      }
      =Count
}
Function Item(x as pointer, index) {
            While not x=>isNull {
                  index--
                  if index else exit
                  x=x=>pnext
            }
             print x=>name$
            ->x
}
Function PopItem(&x as group) {
      m->x
      x=x=>pnext
      Print x=>name$
      \\ new operator -> for returning pointers
      ->m
}
second=Item(a1, 2)
Print second=>name$="Peter"
Print Count(a1)=2
PrintList(a1)
\\ we can get one item as pointer to group
pop1=PopItem(&a1)
Print pop1=>name$
Print a1=>name$
Print "Second try"
PrintList(a1)
Sub PrintList(k1 as pointer)
Print "List Start"
      While not k1=>isNull {
            Print k1=>name$
            k1=k1=>pnext
      }
Print "List End"
end sub



 

Τρίτη, 10 Απριλίου 2018

Έκδοση 9.3 (Πασχαλινή)

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

1. Χρήση Png, με διαφάνεια, τόσο σαν εικόνες όσο και σαν sprites (διάφανα).

2. Χρήση της εντολής Smooth On  (Off) ή Ομαλά Ναι (Όχι) για τα γραφικά όπου οι γραμμές γράφονται με χρωματική εξομάλυνση σε σχέση με τα ήδη τυπωμένα. (anti-aliasing).

3. Χρήση των Διαρθρώσεων για εικόνες (φορτώνονται ως αρχεία, και χρησιμοποιούνται απευθείας σαν να ήταν αρχεία από το δίσκο).

4. Ανανέωση στις φόρμες χρήστη. Όλες οι φόρμες τώρα έχουν τίτλο στην γραμμή εργασιών (task bar) ενώ παλιά μοιράζονταν τον ίδιο τίτλο. Όλες οι φόρμες έχουν Minimized, Maximized (αν μεγαλώνουν), και μπορούν να εμφανίζουν εικονίδιο και μενού επιλογών στην επικεφαλίδα.

5. Δείκτες στις Ομάδες. Μέχρι πριν την 9.3 δεν μπορούσαμε να χρησιμοποιήσουμε δείκτες σε ομάδες. Έπρεπε να βάζαμε μια ομάδα σε ένα στοιχείο πίνακα και να χρησιμοποιούσαμε το δείκτη του πίνακα. Θα δούμε παραδείγματα για το πώς βγαίνουν δείκτες σε ομάδες και πώς χρησιμοποιούνται σε επόμενες αναρτήσεις.


Πέμπτη, 22 Μαρτίου 2018

Revision 3 (Version 9.2) Operators and Light Events for Groups

Revision 3 for Version 9.2 remove a bug in events, and has two implementations, one for operators in groups (a better code, and use of priorities)


1) New extension for operators, using unary, and priorities (low standard, High for * and /), and we can define a right operator for higher priority, and this used for power.
Comparison Operators are always lower priority, and return boolean value (not Group). All other operators return group. Here group has one value (just a public variable), so we can check the evaluation easy.

group alfa {
      n=10
      operator unary {
            .n-!
      }
      operator "-" {
            read b
            .n-=b.n
      }
      operator "=" {
            read b
            push .n=b.n
      }
      operator ">" {
            read b
            push .n>b.n
      }
      operator "<" {
            read b
            push .n<b.n
      }
      operator  "+" {
             read b
              .n+=b.n
      }
      operator right "**" {
             read b
              .n<=.n**b.n
      }
      operator high "*" {
             read b
              .n*=b.n
      }
      operator high "/" {
             read b
              .n/=b.n
      }
      Function Bigger {
            call operator ">", group
            =Number
      }
    
      module operations {
            read z
            call operator "+", z
            call operator "+", z
            call operator "*", z
            call operator "-", z
            m=z
            m.n=100
            call operator "/", m
      }
}

Group Alfa {
      operator "/" {
             read b
              .n/=b.n
      }      
}
z=alfa
k=alfa
k.n=2
z.n=30
m=alfa**k**k+z**k
Print alfa.n**k.n**k.n+z.n**k.n
Print m.n
m=-alfa/-k*-z
Print -z.n*-alfa.n/-k.n
Print m.n
m=alfa*z+alfa*z+z
Print m.n ',  z*ALFA+alfa*z+z>z and 10>2  ' try this
Print alfa.n*z.n+alfa.n*z.n+z.n
Print alfa.n*z.n+alfa.n*z.n+z.n
m=(alfa+z+z)*z
Print m.n, "=(alfa+z+z)*z"
Print (alfa.n+z.n+z.n)*z.n
m=z*(alfa+z+z)
Print m.n, "=z*(alfa+z+z)"
Print z.n*(alfa.n+z.n+z.n)
Print alfa.n
alfa.operations z
Print alfa.n, z.n
alfa*z
Print alfa.n, z.n
alfa-z
Print alfa.n, z.n
m=alfa-z
Print m.n
Print alfa.bigger(z), alfa>z
m=m/z
Print m.n, z.n



2)Light Events for groups:
Group WithEvents Alfa {
      Events "a", "b"
      Χ=10
      Module Check {
            Def M as long
            call event "a", &M, 20
            Print stack.size, M
       }
       Module CheckB(what$) {
            call event "b", what$
      }
}
M=100
a=500
b=4000
Function Alfa_a(New &a,b) {
      M++
      a=M
      Print "ok", a, b, M
      push 500 ' can't return using stack, stack is private
}
Function Alfa_b(a$) {
      Print "From Event:";a$
}
Alfa.Check
Stack ' print empty line, stack is empty
dim k(10)=alfa
Module Z (M()){
      For i=0 to 9{
                  For M(i) {
                        .check
                  }
      }
      M(5).checkb "This is M(5)"
}
Z K()
Beta=k(3)
Beta.checkb "Hello There"
Print a, b ' not changed




The same ouput can we have using Event objects. Event objects have commands like these
Event A Hold
Event A Clear
Event A Release
Event A New aaa() [, bbb()]   ' we can bind some functions for multicast purposes
Event A Drop aaa() [, bbb()] ' we can drop any function
Also These events need to have a signature using a Read command, without "as type". Only the number and kind (by reference using &, $ for strings, ( ) for arrays)
So in Event A variable b can be a number or an object.
In function Alfa_a we have to place New because events call functions as code in module where the function belong, so we have same scope, a New in front in parameter list means Read New &a, b



Group Alfa {
      Event A {
            Read &a, b
      }
      Event B {
            Read a$
      }
      Χ=10
      Module Check {
            Def M as long
            call event .A, &M, 20
            Print stack.size, M
       }
       Module CheckB (what$) {
                  call event .B, what$
      }
}
M=100
a=500
b=4000
Function Alfa_a(New &a, b as long) {
      M++
      a=M
      Print "ok", a, b, M
      push 500 ' can't return using stack, stack is private
}
Function Alfa_b(New zz$) {
      Print "From Event:";zz$
}

Event Alfa.A New Lazy$(&Alfa_a())
Event Alfa.B New Lazy$(&Alfa_b())
Alfa.Check
Stack ' print empty line, stack is empty
dim k(10)=alfa
Module Z (M()){
      For i=0 to 9{
                  For M(i) {
                        .check
                  }
      }
      M(5).checkb "This is M(5)"
}
Z K()
Beta=k(3)
Beta.checkb "Hello There"
Print a, b ' not changed

Τρίτη, 20 Μαρτίου 2018

Αναθεώρηση 2 (Έκδοση 9.2)

Έγιναν ενδιαφέρουσες προσθήκες!
1) Οι μεταβλητές στη κονσόλα αναγνωρίζονται από τον διερμηνευτή τμημάτων ως γενικές ώστε να μην αφήνει σε πέρασμα με τιμή, με ίδιο όνομα γενικής, να χρησιμοποιεί την γενική αλλά να φτιάχνει νέα (αυτό είχε προβλεφθεί από την αρχική 9.2 έκδοση, αλλά δεν είχε υλοποιηθεί, δούλευε μόνο για τις γενικές που φτιάχναμε μέσα σε πρόγραμμα).
2) Νέος Έλεγχος, με δυνατότητα να εκτελεί εντολές και κατά το σταμάτημα, αλλά και κατά την αργή εκτέλεση. Μπορούμε πχ να αλλάξουμε τιμή σε μεταβλητή ή να καλέσουμε κάποιο τμήμα. Για να αλλάξουμε την επιλογή από προβολή σε εκτέλεση αρκεί να πατήσουμε το BackSpace μέχρι να σβήσει όλη η γραμμή και μια ακόμα! Το στοιχείο λειτουργεί όπως και η φόρμα ακόμα και αν τρέχει πρόγραμμα σε αργή ταχύτητα (η δεύτερη επιλογή από τη λίστα πάνω δεξιά στη φόρμα). Η εντολή Δοκιμή ή Test ανοίγει τον έλεγχο, αλλά μπορούμε να τον ανοίξουμε και με συνδυασμό πλήκτρων γραμμάτων και το Ctrl. (τα γράμματα παίζουν όλα όσα δεν χρησιμοποιούνται αλλού, όπως τα C, F, L, M, N, A, V στη κονσόλα). Μπορούμε να καλέσουμε την εντολή και από το πρόγραμμα, ώστε να σταματήσει όπου θέλουμε και υπάρχει και τρόπος για να σταματάει και να συνεχίζει μέχρι μια επόμενη εντολή με συγκεκριμένη ετικέτα. Οι βασικές φόρμες του περιβάλλοντος έχουν την ιδιότητα να μεγαλώνουν, μεγαλώνοντας τα γράμματα, για να είναι θεατά από κάθε χρήστη! Αυτό δεν ισχύει στις φόρμες χρήστη, που δουλεύουν όπως όλες οι φόρμες, αν είναι φόρμες που αλλάζουν μέγεθος στέλνουν γεγονός και κάνουμε ότι θέλουμε. Οι φόρμες περιβάλλοντος έχουν το σκούρο πλαίσιο.



Εικόνα με το τελευταίο στοιχείο να έχει αριστερά το ? και αμέσως μετά γράφουμε μια λίστα στοιχείων για να μας δείξει (πατάμε enter, και παραμένουν σε κάθε επόμενη εκτέλεση, ώστε να βλέπουμε την εξέλιξη). Τα αποτελέσματα φαίνονται στο πεδίο που τώρα δείχνει κώδικα. Αυτό το πεδίο αλλάζει και με κλικ στο Next: (τρίτο στοιχείο της λίστας αριστερά). Επιπλέον τώρα μπήκε και μια προσθήκη, όταν κάνουμε κλικ στο κώδικα να μας δείχνει το κώδικα στη φόρμα της βοήθειας, με την εντολή προς εκτέλεση με κόκκινο χρώμα, ώστε να έχουμε καλύτερη θέαση (απλά σε αυτή την φόρμα δεν έχουμε μετακίνηση του κόκκινου δρομέα, κάτι δηλαδή που έχουμε στο πεδίο αυτό, και επίσης δεν έχουμε χρωματισμένο κώδικα)


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


3) Νέο χαρακτηριστικό στο Combo στοιχείο ελέγχου, το οποίο βέβαια σχετίζεται με το TextBox (το Combo είναι δυο στοιχεία, ένα που βάζουμε πάνω στη φόρμα και ένα δεύτερο που ανοίγει για να επιλέξουμε στοιχείο. Εδώ στην εικόνα έχουμε αυτόματη συμπλήρωση, και το νέο είναι ότι χρωματίζεται το συμπλήρωμα με γκρι χρώμα. (φαίνεται ο ίδιος μηχανισμός και στην φόρμα ελέγχου).


Το πρόγραμμα για τη φόρμα. Είναι με αγγλικές εντολές αλλά μπορεί να γραφτεί και με ελληνικές. Αυτό που δεν φαίνεται στην εικόνα είναι ότι στα στοιχεία  παίζει το Ctrl+F1, το οποίο το φτιάχνει η About (ή Περί). Επίσης εκτός από αυτόματη συμπλήρωση έχουμε προσθήκη νέων λέξεων και ταξινόμηση. Είναι απλός ο κώδικας και γράφεται σε ένα τμήμα Α (με Edit A ή Σ Α) και μετά βγαίνουμε από το διορθωτή με Esc και δίνουμε το όνομα του τμήματος και το enter και τρέχει. Δεν χρειάζεται να βγούμε από την κονσόλα της Μ2000 για να τρέξουμε διαφορετικά προγράμματα. Απλά με τη Σώσε και το όνομα σώνουμε  και με τη Φόρτωσε και το όνομα φορτώνουμε (καλύτερα να δώσουμε Νέο για να σβήσει το παλιά τμήματα και τις συναρτήσεις, γιατί αν υπάρχουν τμήματα με ίδια ονόματα, η φόρτωσε από τη κονσόλα τα "πατάει"). Μπορούμε όμως σε κάθε τμήμα να έχουμε ένα πρόγραμμα (τα τμήματα από τη κονσόλα είναι γενικά, δηλαδή μπορεί ένα οποιοδήποτε τοπικό τμήμα, να τα καλέσει, εκτός και αν υπάρχει τοπικό με ίδιο όνομα, οπότε σκιάζεται το γενικό)

Ενώ η θέαση μεταβλητών περιορίζεται στα τμήματα και στις συναρτήσεις στα τοπικά και σε ότι είναι γενικό, στις συναρτήσεις γεγονότων (καλούνται σαν τμήματα) η θέαση είναι κοινή με την θέαση στο τμήμα που βρίσκονται αυτές. Πχ στη συνάρτηση combo1.dblclick (την οποία καλεί το γεγονός
dblclick του combo1, η τελεία και τα ονόματα πρέπει να είναι ίδια με το στοιχείο και το γεγονός που διαθέτει αυτό αλλιώς δεν μπορεί να κληθεί)  αυτό text1.text$=combo1$  μπορεί να γίνει γιατί το δεξιό μέρος είναι θεατό, και εδώ είναι και το αριστερό. Το text1.text$ είναι ένα αντικείμενο ιδιότητα. Η τελεία στο όνομα μπήκε για γούστο, θα μπορούσαμε να μην τη βάζαμε. Ο διερμηνευτής συνδέει την πραγματική ιδιότητα "text" του στοιχείου text1 που ορίσαμε ότι είναι textbox της φόρμας form1 με την εντολή Declare (Όρισε στο ελληνικό λεξιλόγιο της γλώσσας Μ2000). Η σύνδεση θα τερματίσει όταν τερματίσει το τμήμα ή όταν το στοιχείο δηλωθεί ως τίποτα (δείτε τις τρεις τελευταίες εντολές Declare ....nothing). Η εντολή With (ή Με στο ελλ. λεξ.) χειρίζεται ιδιότητες των αντικειμένων. Ο διερμηνευτής κάθε φορά που χρησιμοποιούμε μια νεα ιδιότητα την θυμάται, οπότε ακόμα και αν δεν την συνδέσουμε με μεταβλητή, στην δεύτερη και επόμενες χρήσεις θα εκτελεί πιο γρήγορα. Οι φόρμες και τα στοιχεία ελέγχου είναι αντικείμενα COM και οι εντολές Method (Μέθοδος) και With (Με) τα χειρίζονται (όπως και κάθε άλλο αντικείμενο COM, όπως το Word). Ορισμένες ιδιότητες τις έχουμε σαν πίνακες, όπως τον πίνακα list$(), για την ιδιότητα "List" του Combo1. Αυτό μπορούμε να το κάνουμε όταν μια ιδιότητα παίρνει παράμετρο.Η Find() αν και είναι ιδιότητα λειτουργεί στην ουσία ως συνάρτηση με μια παράμετρο. Η Μέθοδος μπορεί να καλεί μεθόδους που επιστρέφουν τιμές, και μάλιστα και αντικείμενα και επιπλέον μπορούμε να δηλώσουμε την επιστροφή ΜεΓεγονότα, οπότε θα παίρνουμε και γεγονότα. (αυτά ξεχωρίζουν γιατί δεν δηλώνονται στις συναρτήσεις με τελεία , μεταξύ αντικειμένου και ονόματος γεγονότος αλλά με κάτω παύλα _). Στα αντικείμενα για το παραθυρικό περιβάλλον δεν χρειάζεται τόση εμβάθυνση, λειτουργούν πολύ απλά. Τα νούμερα πχ 8000 είναι σε twips.
Υπάρχει και ένα αστείο στο πρόγραμμα. Την φόρμα την ανοίγουμε και την κρατάμε σε βρόχο (βασικό στοιχείο για να πάρουμε τα γεγονότα) με μια εντολή που περιμένει να πατήσουμε ένα πλήκτρο (Στη φόρμα της κονσόλας). Αν κάνουμε κλικ στην κονσόλα και πατήσουμε ένα πλήκτρο θα κλείσει η φόρμα. Στο γεγονός Unload στέλνω ένα χαρακτήρα στο πληκτρολόγιο με την Keyboard ή Πληκτρολόγιο  η οποία το στέλνει στη κονσόλα και η εντολή Get$ διαβάζει από αυτήν και μόνο, ενώ στις φόρμες έχουμε εισαγωγές από γεγονότα (εδώ για απλοποίηση δεν χρησιμοποιώ τα στοιχεία που δίνει το γεγονός, τα αφήνω δηλαδή στο σωρό τιμών που συνοδεύει τη κλήση, αλλά σε αυτά είναι και μεταβλητή με αναφορά για να ακυρώσει κανείς το τερματισμό της φόρμας).

About call {
      select case About$
      case "is a big name here"
            About  "Title: is a big name here", 8000,6000,"that [is a big name here] easy [too]"
      else
            About  "Title: too", 8000,6000,"that [is a big name here] easy"+About$
      end select
}

Declare form1 form
Declare combo1 combobox form form1
Declare text1 textbox form form1
With form1,"Title" as title$
With combo1,"Edit", True,"UseOnlyTheList", false,"autocomplete", True, "listIndex" as ListIndex,"ShowAlways", True
With combo1,"label","Combo1", "ListText" as item$, "list" as list$(), "text" as combo1$
item$={alfa
            delta
            gamma
            beta
            }
With combo1,"Find" as Find()
Method combo1,"Sort"
combo1$=list$(find("gam*"))

Method combo1,"Move", 1000,1000,6000,600
Method text1, "Move", 1000,2900,6000,600

With text1, "left" as left, "text" as text1.text$ , "ShowAlways", True
Print left
Method form1, "show"
Method text1,"GetFocus"
function form1.unload {
      About
      Keyboard "!"
      show
}
function combo1.about {
      About show "is a big name here"
}
function text1.about {
      About show ""
}
Function combo1.dblclick {
        text1.text$=combo1$
        title$=combo1$
        if find(title$)= -1 then {
         method combo1,"additem",title$
         Method combo1,"Sort"
         listindex=find(title$)
         }
         combo1$=combo1$
          Method text1,"GetFocus"
}
Function combo1.click {
      if listindex>=0 then text1.text$=list$(listindex)
}
Function combo1.scroll {
      if listindex>=0 then text1.text$=list$(listindex)
}
a$=key$ ' loop for holding Forms; Is a joke but works.
Declare Text1 nothing
Declare combo1 nothing
Declare form1 nothing




4) Όπου έχουμε στοιχείο εισαγωγής κειμένου, η λειτουργία Drag and Drop βελτιώθηκε, ώστε σε περίπτωση ακύρωσης της μεταφοράς από ή πρός τη φόρμα, να επαναφέρει τον δρομέα στο σημείο που ήταν. Πχ όταν από μια γραμμή μεταφέρουμε προς τα κάτω κείμενο, τότε οι γραμμές αλλάζουν εμφανίζοντας έναν δρομέα που θα γίνει η εισαγωγή. Αν πατήσουμε Escape ακυρώνουμε την μεταφορά και το στοιχείο γυρίζει στην θέση που ήταν πριν. Αυτό γίνεται στο EditBox, και στο διορθωτή της κονσόλας (είναι διαφορετικά στοιχεία). Το στοιχείο του διορθωτή κονσόλας χρησιμοποιείται και για εισαγωγή κειμένου σε πλαίσιο μέσα στη κονσόλα, οπότε και εκεί έχει την νέα λειτουργία. Αν και λέμε για διαφορετικά στοιχεία, εντούτοις αυτό που διαφοροποιεί είναι η subclass (όρος της VB6) ενός και μόνο UserControl, το οποίο αναβαθμίστηκε σε αυτή την αναθεώρηση. Πχ ο τίτλος της φόρμας alfa είναι το ίδιο usercontrol με το combo1 και το Textbox από κάτω. Όλο το σύστημα παραθύρων είναι "ιδιοκατασκευή", και υπάρχει από την έκδοση 8.1. Υπάρχουν ακόμα περιθώρια βελτίωσης! Η εμφάνιση των στοιχείων είναι ίδια σε όλα τα λειτουργικά που τρέχει το περιβάλλον. Κάτι νέο που έχουν αυτά τα στοιχεία, είναι ότι μοιάζουν περισσότερο με στοιχεία του Android. Πχ τα Buttons (και άλλα στοιχεία) μπορούν να δεχθούν εκτός από κλικ και ολίσθηση δεξιά. Στο κείμενο με κράτημα του αριστερού πλήκτρου του ποντικιού και ολίσθηση προς τα πάνω μετακινούμε το κείμενο προς τα πάνω, το ανάποδο για προς τα κάτω. Το Drag and Drop μεταξύ των στοιχείων γίνεται με πάτημα μια φορά (χωρίς να πιέζουμε συνέχεια το πλήκτρο του ποντικού). Όλα τα στοιχεία υποστηρίζουν unicode χαρακτήρες και αντιγραφές από το πρόχειρο, αλλά δεν υποστηρίζουν γλώσσες που γράφουν από δεξιά (δεν μπορώ να φτιάξω κάτι που δεν μπορώ να το δοκιμάσω).

Κυριακή, 18 Μαρτίου 2018

Έκδοση 9.2 (Αναθεώρηση 1)

Ολοκληρώθηκε η έκδοση 9.2. Πιθανές αναθεωρήσεις θα γίνουν σε περίπτωση που βρεθούν λάθη. Έχει γίνει αρκετός έλεγχος, και διορθώσεις, ώστε να υπάρχει συμβατότητα με τις παλαιότερες εκδόσεις.

Αν και η έκδοση 9.1 μπήκε με την υποστήριξη διάφορων τύπων μεταβλητών, όπως Decimal, Currency, Double, Single, Long, Boolean, ως προς τις σταθερές τιμές πχ το 10000@ είναι Decimal (ή όπως τον λέμε στα ελληνικά στη Μ2000, Αριθμός), για τις μεταβλητές δεν είχε ξεκαθαριστεί ως προς το πότε θα γίνονται μετατροπές τύπων. Γίνονται μετατροπές αυτόματα όταν πχ πολλαπλασιάσουμε έναν Currency (Λογιστικό το λέμε στη Μ2000) με έναν Double θα πάρουμε Double. Το ζήτημα είναι τι γίνεται κατά το πέρασμα με τιμή (by value), και τι γίνεται στο πέρασμα με αναφορά (by reference) που υποστηρίζει η γλώσσα. Αν μια εκχώρηση τιμής αλλάξει το τύπο στην μεταβλητή που προκύπτει από αναφορά τότε αυτό θα είναι άμεσο και στην αναφερόμενη. Αυτό δεν το θέλουμε! Επιπλέον όταν περνάμε με τιμή ενδέχεται να περάσουμε απλά μια έκφραση αντί για μια μεταβλητή (που και αυτή σαν έκφραση θα την δει ο διερμηνευτής) και αυτή να βγάλει έναν τύπο πχ Μακρύς (Long). Αυτό που θέλουμε είναι να μπορούμε να πάρουμε στην παράμετρο την τιμή με το τύπο που θέλουμε, δηλαδή να γίνει μετατροπή κατά τη κλήση.

Στην πρότερη κατάσταση η γλώσσα είχε στο βασικό της σύστημα επεξεργασίας αριθμητικών και λογικών εκφράσεων σαν βάση τον διπλό ή Double (ή πραγματικός σε άλλες γλώσσες, όπως η ΓΛΩΣΣΑ του σχολείου). Μπορούσε να αποθηκεύσει σε Μακρύ ή Long, αλλά οι όποιες πράξεις γίνονταν με Διπλούς. Αυτός ο τύπος (32bit ακέραιος με πρόσημο) είναι χρήσιμος κατά τις κλήσεις εξωτερικών συναρτήσεων σε βιβλιοθήκες "dll". Επίσης για τους λογικούς ή Boolean, απλά χρησιμοποιούσε το 0 και -1, δηλαδή αρθμούς, και έτσι οποιαδήποτε μεταβλητή μπορούσε να παίξει τον ρόλο του Λογικού. Επιγραμματικά δυο ακόμα παρατηρήσεις ως προς το πως ήταν η γλώσσα πριν την 9.2 (1) έκδοση. Οι μεταβλητές (και οι πίνακες) με το % έπαιρναν διπλό εσωτερικά αλλά στις εκχωρήσεις έκαναν αυτόματη αποκοπή δεκαδικών με στρογγυλοποίηση στο μισό. Τα αλφαριθμητικά πάντα ξεχωρίζουν στην γλώσσα γιατί έχουν το $ στο τέλος του ονόματος. Έγινε αναφορά εδώ για τις απλές μεταβλητές (αριθμοί και γράμματα). Περί αντικειμένων θα τα δούμε σε άλλη ανάρτηση, γιατί έχουμε προσθήκες, προχωρημένες, όπως στις ομάδες τελεστής μοναδιαίος, και εκτέλεση εκφράσεων με ομάδες που δεν επιστρέφουν τιμή αλλά κάνουν πράξεις μεταξύ τους και επιστρέφουν αποτέλεσμα ομάδα. Οι ομάδες που επιστρέφουν ιιμή, απλή, λειτουργούν σαν μεταβλητές, με την διαφορά ότι μπορούν να έχουν τμήματα, συναρτήσεις, ιδιότητες.

Για να δούμε τις προσθήκες θα ξεκινήσουμε από το πώς ορίζουμε μια συνάρτηση (οι συναρτήσεις ορίζονται μέσα σε τμήματα, σε συναρτήσεις, σε ομάδες με τον ίδιο τρόπο)

 Στο ξεκίνημα της συγγραφής της γλώσσας οι συναρτήσεις γραφόντουσαν έτσι απλά. Η λέξη Συνάρτηση (Function), μετά ένα όνομα που μπορούσε να είχε τόνους και μπορούσε να κληθεί και χωρίς τόνους, ή και με λάθος τόνους, με μικρά ή μεγάλα, όπως θέλουμε, δεν έχει διαφορά. Και μετά το μπλόκ εντολών, ή σώμα της συνάρτησης. Κάπου μέσα στην συνάρτηση η επιστροφή τιμή γίνεται με ένα = χωρίς κάτι αριστερά, δηλαδή αναφέρεται στη συνάρτηση. Παρατηρήστε ότι έξω από το σώμα δεν φαίνονται οι τυχόν παράμετροι. Οποιαδήποτε συνάρτηση μπορούσε (και μπορεί) να πάρει οπιοδήποτε αριθμό παραμέτρων, και τύπων. Κάθε συνάρτηση έχει έναν σωρό τιμών, και αυτός "γενννιέται" κατά την κλήση. Εκεί μπαίνουν όλες οι τιμές που θέλουμε να δώσουμε. Για να τις διαβάσουμε αρκή η χρήση της Διάβασε.


Συνάρτηση Ένα {
      =100
}

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

Συνάρτηση ΚυβικήΡίζα {
      =Αριθμός^(1/3)
}
Τύπωσε ΚυβικήΡίζα(8)

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

Συνάρτηση ΚυβικήΡίζα {
      Πάνω  ' διπλασιάζει την κορυφή του σωρού
      =Σημ(Αριθμός)*Απολ(Αριθμός)^(1/3)
}
Ν=ΚυβικήΡίζα(-8)
Τύπωσε Ν**3 ' και το ** σημαίνει δύναμη, όπως το ^

Δείτε ότι μια συνάρτηση μπορεί να έχει όρισμα πάλι μια κλήση στην ίδια συνάρτηση, Θα λέμε κλήση σε συνάρτηση όταν αυτή βρίσκεται σε έκφραση, η και εκτός όπως θα δούμε. Με μπλε γράμματα είναι τα γνωστά ονόματα (έχουν αντιγραφεί από τον ενσωματωμένο διορθωτή, και αυτός στην αντιγραφή δίνει και τα χρώματα, οπότε εδώ στο Blog αντιγράφονται άμεσα με χρώμα). Δείτε ότι απαιτήθηκε η στρογγυλοποίηση!

Ν=Στρογγ(ΚυβικήΡίζα(ΚυβικήΡίζα(512))^3^3)
Τύπωσε Ν, Τύπος$(Ν) ' δίνει 512 και Double

 Με χρήση μεταβλητής, δηλαδή θα πάρουμε την τιμή του σωρού σε μια μεταβλητή και θα την δώσουμε δυο φορές στην έκφραση στην εντολή επιστροφής τιμής:
Συνάρτηση ΚυβικήΡίζα {
       Διάβασε χ
      =Σημ(χ)*Απολ(χ)^(1/3)
}

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

Συνάρτηση ΚυβικήΡίζα (χ) {
      =Σημ(χ)*Απολ(χ)^(1/3)
}
ή πιο πρόσφατο (ισχύουν δε όλα τα προηγούμενα)
Συνάρτηση ΚυβικήΡίζα(χ) {
      =Σημ(χ)*Απολ(χ)^(1/3)
}

και επειδή αυτή είναι συνάρτηση μιας γραμμής μπορεί να δημιουργηθεί με την εντολή Κάνε (Def) :

Κάνε ΚυβικήΡίζα(χ)=Σημ(χ)*Απολ(χ)^(1/3)

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

Στο παράδειγμα, η ύψωση σε δύναμη ενώς Decimal (Αρθμός, έχει 29 ψηφία) δίνει πάντα διπλό. Η συνάρτηση αν και χρησιμοποίησε τον Decimal, γύρισε διπλό. Όμως η συνάρτηση έχει καλύτερη ακρίβεια υπολογισμού, και δεν χρειάζεται η στρογγυλοποίηση. Η Ν παραμένει ως Decimal, παρά την εκχώρηση Double από την ΚυβικήΡίζα(). Η Μ δείνχει ότι η ύψωση Decimal σε δύναμη δίνει Διπλό, ή Double.  Το ^3^3 είναι ισοδύναμο με αυτό ^9. Πράγματι 2^9 δίνει 512.

Κάνε Ν ως Αριθμός
Κάνε ΚυβικήΡίζα(χ ως αριθμός)=Σημ(χ)*Απολ(χ)^(1/3)
Ν=ΚυβικήΡίζα(8)
Τύπωσε Ν**3, Τύπος$(Ν) ' και το ** σημαίνει δύναμη, όπως το ^
Ν=ΚυβικήΡίζα(ΚυβικήΡίζα(512))^3^3
Τύπωσε Ν, Τύπος$(Ν) ' δίνει 512 και Decimal (Αριθμός)
Μ=Ν**3
Τύπωσε Τύπος$(Μ) ' Double

Όπως και αυτό (προσθήκη στο προηγούμενο), δείχνει ότι αν φτιάχναμε νέα μεταβλητή με το αποτέλεσμα της συνάρτησης θα γίνονταν Διπλός ή Double.
Ζ=ΚυβικήΡίζα(27)
Τύπωσε Τύπος$(Ζ)

Το κύριο λοιπόν νέο στην 9.2 είναι ότι πήρε τους πολλούς τύπους που μπήκαν στην 9.1 και τώρα κάθε μεταβλητή εντός τμήματος κατά την διάρκεια εκτέλεσης θα έχει τον ίδιο τύπο, ενώ μπορεί να έχει καθοριστεί εντός του τμήματος (ή συνάρτησης), ή να καθοριστεί απ΄έξω (αν δεν ορίσουμε), αλλά και πάλι η μεταβλητή που θα διαβάσει τον τύπο θα παραμείνει σε αυτόν μέχρι να διαγραφεί με το πέρας εκτέλεσης του τμήματος αυτού.

Επιπλέον ενώ υπήρχε η Διάβασε ? η οποία δέχονταν τιμές προεραιτικά δηλαδή, κάποιες μεταβλητές να κρατούσαν την τιμή τους αν δεν δίναμε τιμή (πχ δίναμε συνεχόμενα κόμμα  κατά τη κλήση ή δίναμε το ? που σημαίνει αδιάφορο, πάντα κατά την κλήση), τώρα μια οποιαδήποτε Διάβασε αν έχει το = και έναν αριθμό ή σε αλφαριθμητικά ένα αλφαριθμητικό ως εναλλακτική τιμή τότε, αν οι μεταβλητές δεν υπάρχουν και βρεθεί στο σωρό τιμών αντί για μια τιμή ένας δείκτης που λέει "προαιρετικό" (optional), τότε θα πάρουν αυτές τις αρχικές τιμές.

Ο χαρακτήρας @ όταν ακολουθεί αριθμό σήμαίνει ότι ο αριθμός διαβάζεται ως Decimal (ή Αριθμός). Όταν ακολουθεί # σημαίνει ότι διαβάζεται ως Currency (Λογιστικό το λέμε στη Μ2000), Το σύμβολο ~ είναι  για τους απλούς, και το & για τους τύπου Μακρύς. Οι διπλοί δεν έχουν σύμβολο εδικό. Δείτε ότι ο ψ δεν δηλώθηκε ως τύπος με την Ως <Τύπος>, θα πάρει ότι του δώσουμε, και αν δεν του δώσουμε θα πάρει την δική του "επιλογή", και το τύπο της.


Κάνε ΝιΡίζα(χ ως αριθμός, ψ=2)=Σημ(χ)*Απολ(χ)^(1/ψ)
Ν%=ΝιΡίζα(2) ' χρήση Ν ως ακέραιος
Τύπωσε Ν%**2, Τύπος$(Ν%)
Ν%=ΝιΡίζα(ΝιΡίζα(512, 5), 2)^5^2
Τύπωσε Ν%, Τύπος$(Ν%) ' δίνει 512 και Double
\\ όλες οι μεταβλητές σε % είναι ακέραιες με οποιοδήποτε τύπο:
Μ%=1232133.12312322133321337@*10000000000000000000@
\\ δίνει τεράστιο νούμερο!
Τύπωσε Μ%, Τύπος$(Μ%) 'Decimal
Μ%+=99
Τύπωσε Μ%, Τύπος$(Μ%) 'Decimal


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

Άδειασε
Συνάρτηση δεςμε (κ ως Λογιστικό=2){
      Τύπωσε τύπος$(κ), κ
}
κάλεσε δεςμε(50&)
κάλεσε δεςμε()


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

Κάνε ΝιΡίζα(χ ως μακρύς, ψ ως μακρύς=2)=Σημ(χ)*Τιμή(Στρογγ(Απολ(χ)^(1/ψ),5)->μακρύς)
Ρ=ΝιΡίζα(2131233,8) ' χρήση της συνάρτησης να επιστρέφει Μακρύ  (LONG)
Τύπωσε Ρ**5, Τύπος$(Ρ)


Δείτε λοιπόν πως χρησιμοποιούμε το πέρασμα με αναφορά, με το χαρακτήρα &. Όλα τα αποτελέσματα είναι Decimal

Συνάρτηση ΑύξησεΜετά(&Ν) {
      =Ν
      Ν++
}
Κάνε Αριθμό Κ=2@, Λ, Μ
Τύπωσε Τύπος$(Κ), Τύπος$(Λ), Τύπος$(Μ)
Μ=ΑύξησεΜετά(&Κ)
Λ=ΑύξησεΜετά(&Κ)
Τύπωσε Τύπος$(Κ), Τύπος$(Λ), Τύπος$(Μ)
Τύπωσε Κ, Λ, Μ ' 4, 3, 2


Και τελευταίο για την ανάρτηση. Αλλάζουμε το τύπο της ΑύξησεΜετά(),  ώστε αν δοθεί αναφορά από αλλο τύπο να βγει λάθος,.

Συνάρτηση ΑύξησεΜετά(&Ν ως Λογιστικό) {
      =Ν
      Ν++
}
Κάνε Λογιστικό Κ=2#, Λ, Μ
Τύπωσε Τύπος$(Κ), Τύπος$(Λ), Τύπος$(Μ)
Μ=ΑύξησεΜετά(&Κ)
Λ=ΑύξησεΜετά(&Κ)
Τύπωσε Τύπος$(Κ), Τύπος$(Λ), Τύπος$(Μ)
Τύπωσε Κ, Λ, Μ ' 4, 3, 2

Ζ=10&
Δες οκ {
     Τύπωσε ΑύξησεΜετά(&Ζ)
}
Αν όχι οκ ή λάθος Τότε Τύπωσε Λάθος$
Τύπωσε Ζ ' δεν άλλαξε, γιατί βγήκε λάθος


ΓΚ