Δευτέρα 31 Δεκεμβρίου 2018

Revision 14 Version 9.6

Fix the IF structure

This structure have four possible constructions

1) Using blocks
If condition then {

} else.if condition2 then {

} else.if condition3 then {

} else {

}

or in one line
If condition then {  } else.if condition2 then {  } else.if condition3 then { } else { }
last block maybe omit
If condition then {  } else.if condition2 then {  } else.if condition3 then { } else print "else"

after last block we can use : and place other statements. Those statements are not of the if structure
its structure return 123 because : ? "123"  (? for Print) aren't part of if (because a structure end with a block).

if false THEN {Print "no" } else.if true then {Print "else.if1"} else { ? "ok"} : ? "123"
if true THEN {Print "no" } else.if true then {Print "else.if1"} else { ? "ok"} : ? "123"
if false THEN {Print "no" } else.if true else {Print "else.if1"} else { ? "ok"} : ? "123"
if false THEN {Print "no" } else.if false else {Print "else.if1"} else { ? "ok"} : ? "123"


2) Without blocks
(we can use if condition else for reverse logic)
If condition then

else.if condition2 then

else.if condition3  else

else.if condition3 then

else

end if




3) In one line (we can use blocks or not)
If condition then print 1: print 2 else.if condition2 then print 4 else.if condition3 then print 5 : print 6 else print 7

if last clause has no block  then all statements until the end of line are part of if structure (of last clause)

If false then print 1: print 2 else.if false then print 4 else.if true then print 5 : print 6 else print 7

4) Split structure
(each in one line, no nested, can't be used inside type 2)
if false then Error "not a number"
Else Print "ok"






Σάββατο 29 Δεκεμβρίου 2018

Αναθεώρηση 12 Έκδοση 9.6

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

Πέμπτη 27 Δεκεμβρίου 2018

Revision 10 Version 9.6

I am back in my home in Preveza (Greece), and so we have a new revision.
First a fix done for Stack$() the function to put strings and numbers in a string which can be move to a stack using the Stack statement. Now we can place boolean type and negative numbers (this was a bug).
In the example below, we have three items for a$, a string. First item is a string, second item is a boolean (all comparisons return boolean type), and third is a negative number.

a$=stack$("hello", 3=3, -1)
Stack a$
Print len(a$)=0
Read b$,c, d
Print b$,c, d
Print type$(c)="Boolean"

Second I had an idea before my journey to Athens, so now with little work, works: If we have an inventory type of list as queue, which means we may have same keys, without loosing the priority as we append them (because we can't delete from any position but from the last, using Drop, to drop a number of last keys which we had append to list), we can iterate through same keys.

An inventory list has an array of items and a hash table for keys. When two keys have the same return from hash function they exist in one place in hash table and they maintain a linked list, from the last, so every time Exist() function find the last and return. So now the third parameters if is a negative say to Exist to skip every match until that number get zero. When the third parameter is zero we just increase its value and statements inside Exist() function get that number to return the number of matches for specific key. When we use positive number, say 1, we have to find from the first,  but because the list start from the last, the easy way internal is to find the total and change the parameter to the right negative number.

The code below now is in the help file (the mdb file, which open using Help statement)

a=queue:=1,2:="2A",2:="2B",3,4:="4A",4:="4B",5, 2:="3B"
m=each(a)
\\ $(4) for using proportional printing
Print $(4),"value as string", @(tab(2)),"position - 0 based", @(tab(4)),"key as string in quote"
Print $(0),

While m {
      Print eval$(m), @(tab(2)), eval(m!),@(tab(4)),quote$(eval$(m, m^))
}
\\ new optional parameter for Exist() function
\\ with parameter 0 we get the number of items with same key
Print exist(a,2, 0)=3 ' true
\\ using positive we get the 1st for 1
If exist(a,2,1) Then Print eval$(a)="2A"  ' true
\\ using negative we get last for -1
If exist(a,2,-3) Then Print eval$(a)="2A"  ' true

Print exist(a,4,0)=2
\\ we can iterate same keys using a for loop, and the exist with the third parameter
for i=-exist(a,4,0) to -1
      if exist(a,4, i) then Print eval$(a), ' we get 4A 4B
next i
Print

And this is the same with Greek statements:

α=ουρά:=1,2:="2α",2:="2β",3,4:="4α",4:="4β",5, 2:="3β"
μ=Κάθε(α)
Τύπωσε $(4),"τιμή ως αλφαριθμητικό",@(στήλη(2)), "θέση - από το μηδέν",@(στήλη(4)),"κλειδί σε εισαγωγικά"
Τύπωσε $(0),
Ενώ μ {
      Τύπωσε εκφρ$(μ),@(στήλη(2)), εκφρ(μ!),@(στήλη(4)), παράθεση$(εκφρ$(μ, μ^))
}
\\ νέα παράμετρος για την συνάρτηση Υπάρχει() όταν έχουμε πρώτη παράμετρο ουρά (είδος κατάστασης)
\\ με τιή 0 μας επιστρέφει τον αριθμό στοιχείων (ή 0 αν δεν υπάρχουν) με το ίδιο κλειδί
\\ το κλειδί μπορεί να είναι αλφαριθμητικό  ή αριθμός  (εσωτερικά είναι αλφαριθμητικό)
Τύπωσε Υπάρχει(α,2, 0)=3 '  αληθές
\\ μια θετική τιμή δηλώνει θέση (αν δεν υπάρχει δίνει 0 αν υπάρχει δίνει -1)
Αν Υπάρχει(α,2,1) Τότε Τύπωσε εκφρ$(α)="2α"  '  αληθές

\\ μια αρνητική τιμή δίνει θέση από το τέλος, με -1 το τελευταίο με το ζητούμενο κλειδί
\\ και εδώ επιστρέφει 0 αν δεν υπάρχει ή -1
Αν Υπάρχει(α,2,-3) Τότε Τύπωσε εκφρ$(α)="2α"  ' αληθές

Τύπωσε Υπάρχει(α,4,0)=2
\\ σε συνδυασμό με την Για μπορούμε να δούμε όλα τα στοιχεία με το ίδιο κλειδί
Για ι=-Υπάρχει(α,4,0) έως -1
      Αν Υπάρχει(α,4, ι) Τότε Τύπωσε εκφρ$(α), ' we get 4α 4β
Επόμενο ι
Τύπωσε

Third:|
Git now has the 10 Revision. The 9th was not complete, because I miss an upload.

Τρίτο:
Διαπίστωσα ότι δεν είχα ανεβάσει στο git την 9η αναθεώρηση στην ολότητά της. Τώρα με την 10 ανέβηκαν όλα



Δευτέρα 17 Δεκεμβρίου 2018

Windows 10 High Dpi scaling behavior

For installation M2000 on Windows 10, I found that we have to use override high dpi, from Compatibility, change high dpi settings choose override scaling behavior: Scaling performed by System.



Πέμπτη 13 Δεκεμβρίου 2018

Αναθεώρηση 9 Έκδοση 9.6

Καλά Χριστούγεννα.

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

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

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

class beta {
      structure alfa1 {
            a as long*4
            b as long*4
      }
      structure alfa {
            a as long*4
            b as long*4
            c as alfa1*3
      }
      buffer delta as alfa*3
}
beta=beta()
Print beta.alfa("b")
list


Επίσης μπορούμε τώρα να σκιάσουμε μια ομάδα με μια άλλη, την οποία την ορίζουμε με την εντολή Ομάδα (Group). Σε προηγούμενες αναθεωρήσεις αυτό μπορούσε να γίνει μόνο στο διάβασμα της ομάδας με την Read New ή Διάβασε Νέο από το σωρό τιμών, ή με ορισμό τοπικής και απόδοσης τιμής απευθείας από παράσταση (έκφραση που γυρνάει ομάδα). Με αυτήν την προσθήκη μπορεί κανείς να ορίσει σε ρουτίνες (που έχουν την ίδια θέαση με το τμήμα που βρίσκονται (scope), τοπικές ομάδες οι οποίες στην επιστροφή θα διαγραφούν, χωρίς να τις φτιάχνουμε από κλάσεις ή από άλλες ομάδες.


local group alfa {
      x=10, y%=50, z$="asdasda"
      dim M(4)=10
      event alfa {read b}
      document a$="100"
      class allo {
            q=4
      }
      Group M {
            k=10
      }
      function delta {
           
      }
      module kappa {
           
      }
}
local group alfa {
      x=10, y%=50,z$="asdasda"
      dim M(4)=10
      event alfa {read b}
      document a$="100"
      class allo {
            q=4
      }
      Group M {
            k=10
      }
      function delta {
           
      }
      module kappa {
           
      }
}

List
Modules ?







Roman Numbers (1 to 3999)

To interpret  Roman numbers we have first to find where are the double characters which represents numbers 900, 400, 90, 40, 9 and 4.
If we found one then we have to check from an exclude list if in the right side there are one or more, and if we found one then this is an invalid input.
Also when we found one we can replace it with an internal code.



This is the output of this program:
MMMCMXCIX=3999
LXXIIX=invalid
MMXVII=2017
LXXIX=79
CXCIX=199
MCMXCIX=1999
MMMDCCCLXXXVIII=3888
CMXI=911
M=1000
MCDXLIV=1444
CCCC=invalid
IXV=invalid
XLIXL=invalid
LXXIIX=invalid
IVM=invalid
XXXIX=39
XXXX=invalid
XIXX=invalid
IVI=invalid
XLIX=49
XCIX=99
XCIV=94
XLVIII=48
XLCD=invalid





Module RomanNumbers {
      flush ' empty current stack
      gosub Initialize
      document Doc$
      while not empty
            read rom$
            print rom$;"=";RomanEval$(rom$)
            Doc$=rom$+"="+RomanEval$(rom$)+{
            }
      end while
      Clipboard Doc$
      end
Initialize:
      function RomanEval$(rom$) {
            Flush
            ="invalid"
            if filter$(rom$,"MDCLXVI")<>"" Then Exit
            \\ "Y" is in top of stack
            Push "CM", "MD", "Q"
            Push "CD", "MD","W"
            Push "XC", "DL", "E"
            Push "XL", "X","R"
            Push "IX","V","T"
            Push "IV","I","Y"
            \\ stack flush to doublerom
            doublerom=[]
            \\  "M" is in top of stack
            Data "M", 1000, "Q",900
            Data "D", 500,"W", 400
            Data "C",100,"E",90
            Data "L",50,"R", 40
            Data "X", 10, "T", 9
            Data "V", 5, "Y", 4, "I",1
            \\ stack flush to singlerom
            singlerom=[]
            acc=0
            value=0
            count=0
            stack doublerom {
                  if empty then exit
                  read rep$,exclude$,cc$
                    i=instr(rom$,cc$)
                  if i >0 then {
                        tmp$=mid$(rom$,i+2)
                        L=Len(tmp$)
                        if L>0 then if Len(filter$(tmp$, exclude$))<>L then Break
                        if Instr(rom$,mid$(rom$,i,1))<i then break
                        insert i,2 rom$=rep$
                  }
                  loop
            }
            rom$=filter$(rom$," ")

            stack singlerom {
                  if empty then exit
                  read cc$, value
                  count=0
                  while left$(rom$,1)=cc$ {
                         insert 1, 1 rom$=""
                         count++
                         acc+=value
                  }
                  if count>3 then Exit
                  loop
            }
            if len(rom$)>0 or count>3 Else {
                  =Str$(acc,1033)
            }
      }
      data "MMMCMXCIX", "LXXIIX", "MMXVII", "LXXIX", "CXCIX","MCMXCIX","MMMDCCCLXXXVIII"
      data "CMXI","M","MCDXLIV","CCCC","IXV", "XLIXL","LXXIIX","IVM"
      data "XXXIX", "XXXX", "XIXX","IVI", "XLIX","XCIX","XCIV","XLVIII","XLCD"
      return
}
RomanNumbers


Με ελληνικές εντολές:

Τμήμα Λατινικοί_Αριθμοί {
      Άδειασε
      Διαμέσου Αρχικοποίηση
      Έγγραφο Εγγ$
      Ενώ όχι κενό
            Διάβασε λατ$
            Τύπωσε λατ$;"=";ΤιμήΛατινικού$(λατ$)
            Εγγ$=λατ$+"="+ΤιμήΛατινικού$(λατ$)+{
            }
      Τέλος Ενώ
      Πρόχειρο Εγγ$
      Τέλος
Αρχικοποίηση:
      Συνάρτηση ΤιμήΛατινικού$(λατ$) {
            Άδειασε
             ="άκυρο"           
            Αν Φίλτρο$(λατ$,"MDCLXVI")<>"" Τότε Έξοδος
            \\ θα μπουν ανάποδα, το τελευταίο πρώτο.
            Βάλε "CM", "MD", "Q","CD", "MD","W", "XC", "DL", "E","XL", "X","R", "IX","V","T", "IV","I","Y"
            διπλό_λατινικό=[]
            \\ θα μπουν με το τελευταίο να είναι τελευταίο.
            Σειρά "M", 1000, "Q",900,"D", 500,"W", 400,"C",100,"E",90, "L",50,"R", 40,"X", 10, "T", 9, "V", 5, "Y", 4, "I",1
            απλό_λατινικό=[]
            σύνολο=0
            μια_τιμή=0
            μετρητής=0
            Σωρός διπλό_λατινικό {
                  Αν κενό Τότε Έξοδος
                  Διάβασε απ$, μη_έγγυροι_χαρακτήρες$,χαρακτ$
                  ι=Θέση(λατ$,χαρακτ$)
                  Αν ι >0 Τότε
                        προσωρινή_τιμή$=Μεσ$(λατ$,ι+2)
                        λ=Μήκος(προσωρινή_τιμή$)
                        Αν λ>0 Τότε Αν Μήκος(Φίλτρο$(προσωρινή_τιμή$, μη_έγγυροι_χαρακτήρες$))<>λ Τότε λατ$="A": Έξοδος
                        Αν Θέση(λατ$,Μεσ$(λατ$,ι,1))<ι Τότε λατ$="A": Έξοδος
                        insert ι, 2 λατ$=απ$ '  2 λέμε αλλα δίνουμε 1 χαρακτήρα και ο μεταφραστής θα βάλει ένα διάστημα
                  Τέλος Αν
                  Κυκλικά
            }
            λατ$=Φίλτρο$(λατ$," ")
            Σωρός απλό_λατινικό {
                  Αν κενό Τότε Έξοδος
                  Διάβασε χαρακτ$, μια_τιμή
                  μετρητής=0
                  Ενώ Αρισ$(λατ$,1)=χαρακτ$
                         Παρεμβολή 1, 1 λατ$=""
                         μετρητής++
                         σύνολο+=μια_τιμή
                  Τέλος Ενώ
                  Αν μετρητής>3 Τότε έξοδος
                  Κυκλικά
            }
            Αν Μήκος(λατ$)>0 ή μετρητής>3 Αλλιώς
            =Γραφή$(σύνολο,1033)
            Τέλος Αν
      }
      Σειρά "MMMCMXCIX", "LXXIIX", "MMXVII", "LXXIX", "CXCIX","MCMXCIX","MMMDCCCLXXXVIII"
      Σειρά "CMXI","M","MCDXLIV","CCCC","IXV", "XLIXL","LXXIIX","IVM"
      Σειρά "XXXIX", "XXXX", "XIXX","IVI", "XLIX","XCIX","XCIV","XLVIII"
      Επιστροφή
}
Λατινικοί_Αριθμοί







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

Revision 8 Version 9.6

A bug in Form Next, from previous revision, removed. I make some changes  to the code for the For structure, without blocks (the old one, the faster was ok). But I forgot one statement, to drop one item from return stack. This return stack used only for specific structures, and for subroutines and belong to execution object. Only modules and functions have execution objects.

Also I am working for revision 9, so download this and send feedback, for any bug, to fix it.


Τρίτη 11 Δεκεμβρίου 2018

Revision 7 Version 9.6

Remove two bugs, one from Type$(). Added const and final for lambdas.



const b=lambda->100
const b%=lambda->100
const b$=lambda$->"hello"
Print b%()
Print b$()
Try {
      b=lambda->500
}
Print b()


Another addition for invoking lambda functions, using a hard link. All references by function  (not by variable) to lambda use the old invoking method using a Call Extern Number, where number has the slot where the object (lambda object) exist.

When we make a lambda function, using a variable, interpreter make a function by same name and type (basic types), and from this revision make a hard link, and place empty code. So when we invoke the function, interpreter load code from lambda object, make all closures available to current name space (the scope of lambda), and after the end of execution get back to object all closures. From this revision, interpreter hold a reference to actual object, so if something change the object (if not const) in the slot, before the execution of lambda ends, then the object return to slot.

\\ this is in a global module A
group alfa {
      x=100
      b=lambda->{
            =.x
            .x++
      }
}
\\ get a copy to alfa
beta=alfa
\\ try to change function with a fake one
function alfa.b {
      =500
}
\\ references for functions are strings with code
\\ we get  {CALL EXTERN 3}A.ALFA. (but is not the actual hard link.
\\ actual code is in lambda object. 3 is the actual "slot" where the object exist.
Print &alfa.b()
\\ we can make a link to f() (only for new identifiers)
Link  alfa.b() to f()
Print f()
\\ this function can be changed because has no "hard link" with lambda
\\ all functions except final in groups can be changed
function f {
      =500
}
Print f()=500
Print alfa.b()
Print  beta.b()
\\ we can test pointers
\\ there is two type of pointers
\\ 1. pointers to float groups (holded in containers or by pointers)
\\ 2. pointer to named groups (using a weak reference)
\\ this type has no use when referenced group get out of scope
\\ but as all pointers can change value later
\\ pointers can be null, using p->0 but they hold just an empty group
\\ so never a pointer in M2000 has a real null value, but an "empty" one.

\\ p->(beta) is the same as this:
p=pointer((beta)) ' a copy of beta
Print p=>b(), p=>b()
Print beta.b()
\\ p->beta is same as this
p=pointer(beta) ' as reference to beta
Print p=>b(), p=>b()


So now is an example of recursion, closures, by value and by reference depends of the type of identifier. We can pass variables, array (with parenthesis by copy), pointers to containers as arrays (tuple), inventories (like map) and stacks (linked lists), groups (which are the user objects for OOP),  other lambda functions, event objects, buffers (memory area). We can't pass ordinary functions and  modules (but we can if they are in a group).

n=lambda ->500
a=lambda n (x)->{
      if x<=0 then=0 : exit
      =lambda(x-1)+x+n()
}
Print a(3)=1506
Print a(10)=5055
n=lambda->100
\\ closures are copies, and are like globals for lambda
Print a(3)=1506
\\ closures can be change only from inside
\\ if they are value types (lambda is a value type)
m=lambda->100
a=lambda n, m (x)->{
      if x>5 then n=lambda ->500
      if x<=0 then=0 : n=m : exit
      =lambda(x-1)+x+n()
}

Print a(3)=306
Print a(10)=1055
\\ touple is an array, can have zero items (,)
\\ or one ore more, and it is a reference type
z=(m,)
Link z to Z()
Print Z(0)()=100
a=lambda z (x) -> {
      if x<=0 then=0 : exit
      link z to z()
      =lambda(x-1)+x+z(0)()
}
\\ now we change value in z(0), which is the z
Print a(10)=1055
z(0)=lambda->300
\\ so now lambda change because hold a closure to a reference
Print a(10)=3055
Print eval(z)(0)()=300
\\ without using link we can get the first element in 0 posiiton, and ask for function
\\ this function has a life for the moment of call
\\ interpreter just open the lambda object, invoke, and close again.
a=lambda z (x) -> {
      if x<=0 then=0 : exit
      =lambda(x-1)+x+Eval(z)(0)()
}
Print a(10)=3055


Another one small example using pointers for groups.



class a {
      counter as long
}
b=lambda k=pointer(a()) (x)-> {
      k=>counter+=x
      \\ we can return pointers from groups (if they are float type)
      ->k
}
m=b(30)
Print m=>counter=30
\\ get a pointer and convert it to a named group, and then return  a float group (as is, without pointer)
def copy(x as group)=x
k=copy(b(300))
z->copy(b(300))
Print z=>counter=630
Print m=>counter=630
Print z is m ' false
z->b(300)
Print z is m 'true
Print z=>counter=930
Print k.counter=330 ' old value
 

The same as above but without using copy() user function


class a {
      counter as long
}
b=lambda k=pointer(a()) (x)-> {
      k=>counter+=x
      ->k
}
m=b(30)
Print m=>counter=30

group k=b(300)
z=b(300)
Print z=>counter=630
Print m=>counter=630
Print z is m ' false
z->b(300)
Print z is m 'true
Print z=>counter=930
Print k.counter=330 ' old value