Παρασκευή, 27 Απριλίου 2018

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

Το αρχείο εγκατάστασης ενημερώθηκε στην αναθεώρηση 4.

Λάθη:
1. Επαναφορά του Εγγράφου στις ομάδες. Είχε από λάθος βγει εκτός, από την 9.3 αναθεώρηση. 0, διορθώθηκε
2. Εύρεση ενός δύσκολου λάθους, που εμφανίζονταν σε ορισμένες περιπτώσεις σε ομάδες όπου κατά την αντιγραφή έχαναν σε συναρτήσεις τον κώδικά τους! Για να συμβεί αυτό έπρεπε να γίνει ένας συνδυασμός "προγραμματισμού". Τώρα άλλαξε εσωτερικά το σύστημα πιο γενικά:

Global group m {
      function k {
            =1000
      }
}
class alfa1 {
      m=100
      function k {
            =500
      }
      N=10
      module alfa1 {
            \\ in this line was the problem
            \\ code to prevent alter global group m
             m=this ' copy this group to m
            m=m
            m.N=500
            this=m ' copy m to this group
            Modules ?
      }
}
alfa=alfa1()
Print m.k()
Print alfa.N, alfa.k()
Report &alfa.k()
alfa=alfa
Modules ?
Report &alfa.k()
Print alfa.N, alfa.k()
\\ also
Print m.k()

3 Διορθώθηκαν όλα τα ελληνικά μηνύματα (σε Word).
4. Το F12 στην βοήθεια δείχνει σωστότερα τα τμήματα/τις συναρτήσεις και με κλικ ανοίγει το κώδικά τους.
5.Νέος Διακόπτης "ext"  ( +ext, -ext με το δεύτερο  ως η εξ ορισμού επιλογή). Η επιλογή +ext  επεκτείνει την εμβέλεια (scope) των μεταβλητών τμημάτων (προς το παρόν όχι των πινάκων), ώστε να είναι θεατά με πρόθεμα το όνομα του τμήματος σε τμήματα που δημιουργούνται εντός των τμημάτων και εκτελούνται εκεί. Ο διακόπτης +sec χριάζεται και τον +sec (που είναι εξ ορισμού έτσι), γιατί μόνο στο secure interpreter μπορεί να έχει αποτέλεσμα.
Οι διακόπτες  φαίνονται με την εντολή Monitor ή Έλεγχος στη γραμμή εντολών (ή από κώδικα με την Set ή Θέσε  πχ Set Monitor. Μην το μπερδεύεται με την δεύτερη ή τρίτη οθόνη προβολής. Για να εμφανίσουμε τη φόρμα (κονσόλα) της Μ2000 σε άλλη οθόνη (pc monitor) δίνουμε την εντολή Παράθυρο (Window) με τον αριθμό μεγέθους χαρακτήρων και το νούμερο της οθόνης: Πχ Παράθυρο 16, 1 θα κάνει τα γράμματα 16pt και θα ανοίξει την κονσόλα (ή θα την μεταφέρει, καθαρίζοντάς την) στο δεύτερο μόνιτορ (αν υπάρχει). Όλες οι φόρμες και η κονσόλα υποσηρίζουν πολλαπλά μόνιτορ. Πχ μια φόρμα που κάνει αλλαγή μεγέθους μπορεί να επεκταθεί με το πάτημα ενός κουμπιού στο μέγεθος της οθόνης (μόνιτορ) όπου δώσαμε την "εντολή".

Στο παρακάτω παράδειγμα οι alfa.kappa και alfa.beta και η Alfa.N είναι θεατά από το τμήμα beta (όταν εκτελείται).  Τον πίνακα Α(10) τον περάσαμε με δείκτη (τον Ν).
Δεν χρειάζεται στην ουσία αυτός το τρόπος, γιατί μπορούμε να περνάμε με αναφορά:

set switches "+sec +ext"   ' need secure interprer (default) and extended scope ( -ext is the default)
Module alfa {
      kappa=10
      beta$="ok"
      \\ we can't pass arrays with that way
      Dim A(10)=5
      \\ we have to use a pointer
      N=A()
      Module beta {
            Print alfa.kappa, alfa.beta$
            alfa.kappa++
            Dim K()
            K()=Alfa.N
            Print K(4)
      }
      beta    ' 10
      beta    ' 11
      Print kappa '12
      Module zeta {
            ' we use <= same for globals
            alfa.kappa<=500
            ' using = we make a local variable
      }
      zeta
      Print kappa
}
alfa

Second Example (same output)

set switches "-ext"   ' reset  ext
\\ using by reference
Module alfa {
      kappa=10
      beta$="ok"
      Dim A(10)=5
      Module beta (&kappaRef, &betaRef$, &Aref()) {
            Print alfa.kappa, alfa.beta$
            kappaRef++
            Print Aref(4)
      }
      beta &kappa, &Beta$, &A()
      beta &kappa, &Beta$, &A()
      Print kappa '12
      Module zeta (&kappa) {
            kappa=500
      }
      zeta &kappa
      Print kappa
}
alfa



6. Βελτιώσεις στις φόρμες χρήστη.
6.1 Η λίστα επιλογών πάνω στην επικεφαλίδα, για αλλαγή μεγέθους, μετακίνηση παραθύρου και άλλα βασικά, ανοίγει με κλικ σε ένα εικονίδιο με τρεις οριζόντιες γραμμές. Όταν είναι επιλεγμένη η επικεφαλίδα της φόρμας, τότε αυτό είναι σε άσπρο χρώμα. Αν πατήσουμε το κάτω βελάκι θα ανοίξει  η λίστα. Αν πατήσουμε στην ανοικτή λίστα τα αριστερά - δεξιά βελάκια, τότε κλείνει η λίστα και επιλέγεται από την φόρμα το τελευταίο στοιχείο που είχε επιλεχθεί.


6.2Στο στοιχείο Κείμενο (EditBox) η εισαγωγή νέου κειμένου (από αρχείο) επαναφέρει τον δρομέα στην θέση 1,1.


7. Πώς ορίζουμε μεταβλητές (με αγγλικές εντολές)

\\ Definition of variables
\\ Locals/Gobals with shadow function
\\ In this example we see how to define variables
\\ by using an assignment of a numeric literal of specific type
\\ And what happen if we assign another type
\\ We set a switch to get True/False for booleans at Print
\\ we use Set to send line to Command Line Interpreter (CLI)
\\ SBL means Show BooLeans
Set switches "+SBL"
Module AnyName {
      A=100&
      Print Type$(A) 'Long
      A=2+3 ' 2 and 3 are doubles
      Print Type$(A) ' Long
      A=2%+3% ' 2% and 3% are integers 16 bit
      Print Type$(A) ' Long
      For This {
            \\ This is a block for temporary variables
            \\ Local has the ability to make new variable
            \\ without erasing the old one, with same name
            \\ it is not good to use it in loop, because we will fill the memory
            Local A=100@
            Print Type$(A) ' Decimal
            Set Push Valid(A)
            Read ok as boolean
            Print ok, type$(ok) ' false - there is no global with A name
            \\ Old A shadowed
            \\ Global variable can't changed, if a same local exist before
            Global A=100
            Print Type$(A) ' Decimal
            Set Push Valid(A)
            Read ok
            Print ok, "Global A exist" ' true
            Global A as Double=100
            Print Type$(A) ' Decimal
            \\ now we have 1 local more, and 2 global more
      }
      \\ now all temporary variables erased
      \\ so we get the old value
      Print Type$(A) ' Long
      \\ Now we define a global one
      Global B as Currency=100
      Print Type$(B), B
      \\ To change a global we use <=, because = make a local one which hide global
      B<=10000@
      Print Type$(B), B
      \\ Using Set statement

   \\ We send line to CLI, so anything has to be global (we can't place a local variable)
      \\ Also if Global C exist, no new global declared, we overwrite in it
      Set C=100@
      Print Type$(C) ' Decimal
      Set C=200%
      Print Type$(C) ' Integer
      Set C=200&
      Print Type$(C) ' Long  
      Set C=100@
      Print Type$(C) ' Long can't be changed if chosen once.
      \\ To place Local A to C
      C<=A*2
      Print C
      Let C=A*2
      Print C
      \\ we can observe the variables using List
      List
      \\ We can usine Set. We can send weak referencre to stack
      Push Weak$(A)
      \\ and read it as Letter$, and resolve with Eval()
      Set C=Eval(Letter$)*2
      Print C
      \\ Or better
      Push A : Set Read C
      \\ Or make a link from a local to global one
      \\ we have to use New, because no 2nd reference allowed
      Print A
      Push &A : Set Read &C1
      A++ : Print C1
      C1<=10
      Print A=10 ' true
}
\\ we call AnyName
AnyName
Print "Done"
List
\\ we get an empty list, no variables exist from AnyName


Υπάρχει και δεύτερο παράδειγμα:

\\ Example 2
\\ define variables once
\\ we can't call def for same variable in same scope
Form 80, 40 ' we need some lines more
Flush
def a as boolean
def integer c, d
def currency c1, d1
Print type$(c), type$(d), type$(c1), type$(d1)
Print a
Push 100
read k as boolean
Print K
\\ we can use Module Z(k as boolean)
\\ but is better for Modules to have a space between Z and left parenthesis
\\ for seaching through F2/F3 (and shift F2/F3) from internal code editor
Module Z (k as boolean) {
      Print k
}
Z 100 ' show true
Module Z {
      Read k as boolean
      Print "Second Definition, replace old one"
}
Z 200
Module Z {
      Read k ' no type ' can't be string
      Print Type$(K), K
 
}
Z 100@ ' decimal
Z 100# ' Currency
Z 100& ' Long
Z 100~ ' Single  ' no need decimal part
Z 100 ' double  ' no need decimal part
Z 100% ' Integer
Z 0xFFFFFFFF ' double - used as unsigned
Z 0xFFFFFFFF& ' Long  - signed
Z 0xFFFF%'  Integer - signed
Z ! 100 ' ! convert to long
Z %K=123456789123456@ ' decimal, passing by name
\\ passing by name can't be used with a Call to a module
Call Z, 123456789.12# ' currency
\\ Calling a module in any of two types of calls, send current stack of values
\\ It is duty of calling module to leave stack as expected
Push 12344&
Call Z ' long
Push 1234%
Z  ' integer
\\ some magic here
Module Z (x as integer=100) {
      If Valid(K) Then {Print "K exist as ";Type$(K), K} Else Def K=10%
  
      Print Type$(x), x
      If Module(M) Then Print "I Found M" : Call M, K
}
Z %K=100@, %X=500@ ' show K as Decimal and X as Integer
\\ this is a risk call, if we have something in stack
Z  ' show X as Integer with value 100
\\ this is no risk call, we place ? as "get your optional value"
Z ?
Push 500
Z %K=100& ' using a pass by name insert a ?
Print Number=500 'true
Z 200, %K=200~
Module B (k){
           Print Type$(k), k, "(I am B)"
}
\\ Using this type of call we can place a module before call
\\ this "simple" call (without Call), can't be used for recursive call in modules
Z 200, %K=100; M as B
Z ? ; M as B
Module EatNumbers {
      While IsNum {
            Print Number,
      }
      Print
}
\\ there is no actual number for parameter passing
\\ If we read, using Read or Number, or Letter$ from Stack and there is no value we get an error
EatNumbers 1,2,3,4,5
\\ define again same module
Module EatNumbers {
      If Empty Then Exit
      Read x
      Call EatNumbers
      Print x,
}
\\ Reverse order using recursion
EatNumbers 1,2,3,4,5
\\ we have to exclude Print to be used at the end
Print
\\ we can redefine module to include Print, using an inner module
Function Z {
             Module Inside {
                  If Empty Then Exit
                  Read x=100
                  Call Inside
                  Print x,
            }
            Inside
            Print
}
M=Z(1,2,3,4,5)


Τέλος θα βάλω και ένα παράδειγμα με δείκτες Ομάδων (νέα δυνατότητα στην έκδοση 9.3):
 Βάζουμε ένα αντίγραφο της ομάδας alfa στη Κατάσταση beta, στο κλειδί "10".   Φτιάχνουμε έναν δείκτη a με το βελάκι (δυο χαρακτήρες ->) . Με τη χρήση του For (Για) ανοίγουμε την ομάδα και εμφανίζουμε το .χ που είναι 10. Πριν κλείσει το beta("10") πειράζουμε την χ από το δείκτη a, το οποίο γίνεται 11. Βγαίνουμε εκτός της For (τώρα το beta("10") κλείνει (από στατικό πρόσκαιρα γίνεται "κινητό", πάει όπου πάει και ο πίνακας). Αυξάνουμε την α=>χ κατά 100 και βλέπουμε ότι έχει την ίδια τιμή με την beta("10").x. Αυξάνουμε το α=>χ κατά 1 και το beta("10").x  ακολουθεί. Μετά κάνουμε την αύξηση από το beta("!0").x και φαίνεται αμέσως στο α=>χ.



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


Και πιο ωραίο ακόμα. Εδώ στην συνάρτηση alfa αντί για = έχουμε το -> για να επιστρέψουμε δείκτη. Αν βάζαμε το ->κ θα επιστρέφαμε δείκτη σε στατικό αντικείμενο, πράγμα που θα έβγαζε λάθος στη πρώτη χρήση, γιατί το k θα διαγραφεί στον τερματισμό της alfa(). Η επιστροφή τιμής δεν προκαλεί τερματισμό στην Μ2000. Με την παρένθεση παίρνουμε αντίγραφο του αντικειμένου, και με το βελάκι παίρνουμε δείκτη σε αυτό το αντίγραφο, το οποίο θα παραδωθεί από την alfa(). Έτσι η m θα γίνει δείκτης σε ομάδα!
Η συνάρτηση Ομάδα() ή Group() επιστρέφει πάντα ομάδα. Έτσι η Group(m) θα δώσει αντίγραφο της ομάδας που δείχνει η m. Χωρίς την χρήση της συνάρτησης, με μια stat=m θα παίρναμε έναν δείκτη ακόμα. Η m->Stat βγάζει δείκτη αλλά για στατικό αντικείμενο. Όταν "πεθάνει" η Stat η m θα είναι άχρηστη γιατί δεν κρατάει πραγματική αναφορά σε αντικείμενο, αλλά ισχνή αναφορά στο "απόλυτο όνομα" του στατικού αντικειμένου. Όπως έχουμε δυο είδη ομάδων έτσι έχουμε και δυο είδη δεικτών στις ομάδες, απλά δεν φαίνεται άμεσα η διαφορά τους, αφού ένας δείκτης του ενός είδους γίνεται να δείξει αργότερα με το άλλο είδος.
Μετά δείχνουμε πώς μηδνίζουμε το δείκτη ώστε να μην έχει αναφορά σε ομάδα. Και μετά φιτάχνουμε ένα δείκτη στην ομάδα, ο οποίος είναι σε στοιχείο πίνακα.

function alfa {
      group k {
            x=10
            module alfa {
                  Print .x
                  Print this.x
            }
      }
      ->(k) ' use of () to produce a copy of k
}
m=alfa()
Print m=>x
m=>alfa
For m {
      Print .x
      Call .alfa
}
List  ' only m pointer in List
Stat=Group(m)
List  ' Now exist Stat (Group), Stat.X
Modules ? ' Exist Stat.Alfa
m->Stat ' Pointer can change where points to
m=>x=500
Print Stat.x=500 ' True
\\ we can add two more variables
Group Stat {
      y=10200@, z as integer=200
}
\\ So now pointer know about this;
Print Stat.z = m=>z ' true
\\ we can place null to drop the reference
m->0
Print Valid(m=>z)=false ' true, is not valid
Dim A(39)
A(3)->Stat
Print A(3)=>z=200 ' We can place pointers in arrays
Def ExpType$(x)=Type$(x)
Print ExpType$(A(3)=>z)="Integer"  ' true
For A(3) {
      Print ExpType$(.y)="Decimal"  ' true
}
 


Αυτά για την ώρα..θα ετοιμάσω και άλλα παραδείγματα με δείκτες!