Παρασκευή 29 Μαρτίου 2019

Revision 14 Version 9.8

Some bug fixes.
1) Fix for passing array items by reference. Before works if we make a call from a module. The problem was the call from a function.
This work on previous revision 13
module b {
 dim a(10)=-1
 inc=lambda ->{
  stack
  read &x
  x++
 }
 call inc(&a(3))
 Print a(3)
}
call b
b

but not this (work nice in revision 14):
function b {
 dim a(10)=-5
 inc=lambda ->{
  stack
  read &x
  ? x
  x++
 }
 call inc(&a(3))
 Print a(3)
}
call b()
n=b()
Also the above programs show the stack (as we call) before the reading (and linking to a variable). An Array item passed by reference with a copy in copy out method. First a temporary variable hold a copy of array item, then the reference of that variable send to stack, so the read &x make x as a link to temporary variable (so x has no own data, it is an alias of the temporary variable). Also for this call interpreter save to a special collection the data which need to make the copy out at the end of the call.
The stack statement, inside function, show the strings (as references) of the temporary variables which interpreter produce. If array for some reason lost the item which we have to copy out, no error produced, the interpreter just do nothing for store back the value from temporary variable.

global z=2
function k (&n, &x) {
 x++
 n++
 Print x
}
dim a(3,3)
a(z,1)=100
call k(&z, &a(z,1))
Print a(2,1)=101, z=3
z<=2   ' need <= to assign a value to a global, otherwise we get a local one
\\ change the k (also change the signature too)
function k  {
 z++
 read &x
 x++
 Print x
}
\\ indexes calculated before the call
call k(&a(z,1))
Print a(2,1)=102, z=3


2) Another fix is in Each() function which return an iterator object. There are two forms, one using comma and another without, using a descriptive text.

Here is the program which make for Rosettacode.org (Four bit adder), which found the errors, and immediately fix them.


ha means half adder, fa is a full adder. We simulate bits using just values 0 and 1 (these are doubles, the default type for numbers). For this reason we don't use And operator or Binary.And() for binary And, and the other gates, but we have three arrays, as functions, for not(), and(), or(). Also task want to have a function for xor, so xor isn't an array.
Then we make lambda with closures whatever need each one. Lambda add4 need fa as a closure.
The add4 may work from one or more bits (so name is not exactly a match for this implementation)
We have a lambda called source which get a number of values, in a private stack, then reverse the order and return an array of these values. We do that to send the left most value as the last item of array. The output just written in the res()  array, which we pass by reference (this is not a copy in-copy out process, but a simple alias, the two names. res() and out() are local on different scopes, on same data). So to print the result first we have to print the carry, and next the top value res(3) until the res(0). So we make k as an iterator (which hold a pointer to array res(), plus other data, and the cursor, which we can access using k^), which work in a While {} or in a Print statement. Here in a print statement we get all values each on one column, and may wrap to next line if no column left in line.

\\ when we use Call we pass the same stack in the call, so we need to clear the stack before
\\ or we can use a block for a new stack: Stack New  {}
\\ when the block exit the old stack return as current stack.
\\ so here Flush empty the current stack
Flush
dim not(0 to 1),and(0 to 1, 0 to 1),or(0 to 1, 0 to 1)
not(0)=1,0
and(0,0)=0,0,0,1
or(0,0)=0,1,1,1
xor=lambda not(),and(),or() (a,b)->or(and(a,not(b)), and(b, not(a)))
ha=lambda xor, and() (a,b, &s, &c)->{
 s=xor(a,b)
 c=and(a,b)
}
fa=lambda ha, or() (a,b,c0, &s,&c1)->{
 def sa,ca,cb
 call ha(a,c0,&sa,&ca)
 call ha(sa, b, &s,&cb)
 c1=or(ca,cb)
}
add4=lambda fa (inpA(),inpB(),&v, &out()) ->{
 dim carry(0 to len(InpA()))=0
 for i=0 to len(InpA())-1
  mm=fa(InpA(i),inpB(i),carry(i),&out(i),&carry(i+1))
 next
 v=carry(i)
}
dim res(0 to 3)=-1
source=lambda->{
 shift 1, -stack.size  ' reverse stack items
 =array([])  ' convert current stack to array, empty current stack
}
def v
call add4(source(1,0,1,0),source(1,0,0,1),&v, &res())
'k=each(res(), -1, 1) ' another way to do the same as the later
k=each(res() end to start)  ' k is an iterator, now configure to read items in reverse
Print v, k

3) Fix at EditBox when it is in a M2000 mode (for displaying M2000 code), for the F2 and F3 when we mark an identifier (any type), works nice (before a flag make the F2 and F3  to work for words only). This problem not exist if we pass a list of identifiers for syntax color.

4) Added Hex statement in Help File.(there is a Hex$() but for no reason I never make a record for Hex statement, a special Print for results in Hexadecimal)








Σάββατο 16 Μαρτίου 2019

Multiple Inheritance (Changed from Version 10)

Multiple Inheritance, no need for virtual Inheritance.
A class is a global function which return a new group (the user object). A module with same name as the class is the constructor. Label class: make the members of the class after it to be used only in the group inside class definition and not listed as members returned to final object. So constructors at Mammal, WingedAnimanl and Bat are used once, and not included in Bat group.
this=Animal() merge Animal() to this

In Bat constructor we merge two times the this object, one with Mammal() and one with WingedAnimal(). But when we call Mammal() we get also a merged group with Animal(). And when we call WingedAnimal() we get also a merged group with Animal(). Because merging is a flat type, we get only one animal inside bat. The second animal merged with the first one.


**New for version 10 & 11***
Class Animal {
        module eat {
                Print "I am Aninal and now I eat you"
        }
}
Class Mammal as Animal {
        module breath {
                print "I am breathing now"
        }
}
Class WingedAnimal as Animal {
        module flap {
                print "I am flapping my wings now"
        }
}
Class Bat as Mammal as WingedAnimal{
}
Animal=Animal()
Mammal=Mammal()
Bat=Bat()
Bat.eat
Bat.breath
Bat.flap
Print valid(@Mammal as Animal)=True
Print valid(@bat as Animal)=True
Print valid(@bat as Mammal)=True
Print valid(@Animal as Mammal)=False
Print Animal is type Animal=True
Print Animal is type Mammal=False

A different approach, is when we use a Superclass. A group may have a link to a superclass. A superclass is a group with no visible members. We can create a group using a superclass (a group in a group may have a different superclass). A superclass can't have another superclass (for current 9.8 version of M2000 Interpreter). A Superclass may have unique members. We can change a class member eat. but we can call superclass member eat from a group which linked to sAnimal. So statement For SuperClass {.eat} call SuperClass eat member.
If we have in mammal a different superclass, from WingedAnimal, we get a bat with all members from the two classes Mammal() and WingedAnimal(), but we get a link to last superclass. We can choose the superclass using the right order on the two statements This=Mammal() and This=WingedAnimal() in Bat constructor.
Using Superclass we get the "class" members. With it,there are only instance members.

A superclass has no constructor. We can access superclass only from a group which get this superclass as own. But we can add some members, and that members may have the constructor to change state of the superclass own members. We haven't access to private members, but we have access to unique members. So unique members are not private members, but only a group which have access to superclass can use these unique members, so we can change the state of a superclass using these unique members. To make unique members we use Unique: label and all members after that label belong to unique members

Labels for changing definitions inside group are Public:, Private:, Unique: and Class:
Also we can use Final for variables and functions/modules (for these the keyword final inserted after the keywords function and module). A final member can get value once. If a member is not final but merge with another group which have a same name member but final then the value of member will be final. In another merging the changing of value ignored for final members (no error raised).


Superclass Global sAnimal{
        module eat {
                Print "I am Aninal and now I eat you"
        }
}
Class Mammal {
        module breath {
                print "I am breathing now"
        }
Class:
        module Mammal {
                this=sAnimal
        }
}
Class WingedAnimal {
        module flap {
                print "I am flapping my wings now"
        }
Class:
        module WingedAnimal {
                this=sAnimal
        }
}
Class Bat {
class:
        module Bat {
                this=Mammal() with WingedAnimal()
        }
}
Animal=sAnimal
Mammal=Mammal()
Bat=Bat()
Bat.eat
Bat.breath
Bat.flap
Print valid(@Mammal as Animal)=True
Print valid(@bat as Animal)=True
Print valid(@bat as Mammal)=True
Print valid(@Animal as Mammal)=False
Print Animal is type sAnimal=True
Print Animal is type Mammal=False


Tail Recursion

Normally a call to a function in an expression, in M2000, pass a new stack with values, and a Read statement read these values. We can define a type and a number, on just a number if it is double, for some arguments, as the default value, so when the Read statement define the variable, and there is no value in stack, then assign the default value.

This is an example which we use a Restart at the end of function, to call the function body. the parameter list convert to a Read statement, so the actual function body has one more line for these functions. (one function has the parameter list with as space after the name, this is the same without the space).
The second call, using restart, has to use a proper feeding



\\ Factorial tail Recursion
Function TailRecursion (x, z as decimal=1){ 
        z*=x
        If x<=1 Then =z: Exit
        Push z, x-1  ' fix stack
        Restart  ' call again
}
Print TailRecursion(10), TailRecursion(5)
Print TailRecursion(1), TailRecursion(20)
\\ Fibonacci tail recursion
Function fibTailRecursion(x, f0 as decimal=0, f1 as decimal=1) {
        If x<=1 Then =f0: Exit
        Push  f0+f1,f1,x-1
        Restart
}
For i=1 to 134
        Print fibTailRecursion(i), i
Next

We can use stack to save multiple results. The statement shift 1,-stack.size reverse the order of stack items. So now the Push statement push another value, which stay to stack, and because the last value push to top (we say at position 1 of stack items), we have to reverse the items. The [] is a keyword, an identifier which tell to interpreter to return the pointer to current stack, and leave an empty stack as the current stack, so we move the current stack to return value. Variable z now is a pointer to a stack object. The print statement when get a container type object like array, pointer to array, stack and inventory (a kind of vector) make a local iterator and print each item in separate column, and change row if needed. Only strings and numbers renderer to screen, and objects types are rendered as a space. So print statement leave an empty column, in current row, and advance to next column and or next row.


Function fibTailRecursionStack(x, f0 as decimal=0, f1 as decimal=1) {
        Push f0
        If x<1 Then Shift 1,-Stack.size : =[]: Exit
        Push  f0+f1,f1,x-1
        Restart
}
Z=fibTailRecursionStack(10)
Print Z
For i=0 to 5
        Print fibTailRecursionStack(i)
Next


We can use a lambda function too. The function part is the same. We have no closures here.
 
fibTailRecursionStack=lambda (x, f0 as decimal=0, f1 as decimal=1)-> {
        Push f0
        If x<1 Then Shift 1,-Stack.size : =[]: Exit
        Push  f0+f1,f1,x-1
        Restart
}
Z=fibTailRecursionStack(10)
Print Z
For i=0 to 5
        Print fibTailRecursionStack(i)
Next


Because M2000 is an interpreter. a function call is more than one function call in machine code. If name of functions has $ then a call to a function for string function called first. This function find the function by the name in a Hash Object, a fast way to find the code of function. Then a new execution object prepared, then parameters processed and placed in a new stack object, and then the function called passed the process object and the function's reference. The code from function's reference "loaded" in a string and passed to execution. If a restart happen then the code loaded again.

 We can separate the f0 and f1 parameters from parameter list using a second lambda, inside the fibtailRecursionStack. Now we call two functions, but the second one using the Call statement. A call statement pass the same stack of values, because is a call of the function like it is a module. Before the call we do a flush to stack (so stack start as an empty). We pass only the x in the call to fibaux function. I another implementation we can check if the x is valid for the calling. The Fibaux has no return value, all values stay at stack, at the exit.

If we want to get the first 5 items (including 0) we call Fibaux with x-1
 Or if we want to drop 0 then before exit we insert a Drop statement without a value (is same as Drop 1). so the statement change to
 If x<1 then Shift 1,-Stack.Size: Drop:Exit


Fibaux=lambda  (x, f0 as decimal=0, f1 as decimal=1) -> {
        Push f0
        If x<1 Then Shift 1,-Stack.size : Exit
        Push f0+f1,f1,x-1
        Restart
}
fibTailRecursionStack=lambda Fibaux (x)->{
        Flush
        Call Fibaux(x)
        =[]
}
Z=fibTailRecursionStack(5)
Print Z

 About stack statements DROP, SHIFT, SHIFTBACK, OVER, PUSH, DATA, FLUSH
The flush statement leave an empty the stack. The Push statement push a value to stack at the top. A Push 1,2,3 push all values to the top, so 3 is the new top. A Drop statement is same like Drop 1, which drop 1 item from the top. So a Frop1 leave stack with 2 the new top, and 3 after it. An Over 2 make a copy of 3 to new top (internal is an indirect copy, we copy the pointer which point to 3). An Shift 3 shift the third item to position 1. A ShiftBack 3 send the top after the current third item, so the third item became the second one. Data push items to end of stack. Variable Empty is true if stack is empty. Also Stack.Size return the size in items of stack. SHIFT, SHIFTBACK and OVER get a second parameter, the repeat factor. This factor if is negative then change the behavior of statement Shift and ShiftBack.



Flush
Data 1,2,3,4
Stack' display the Stack in console1 2 3 4
Shift 3,-2
Stack ' 4 3 1 2
Over 3, 2
Stack' 3 1 4 3 1 2
Shift 3, 2
Stack'4 3 3 1 1 2
Over 1, 4 
Stack ' 4 4 4 4 4 3 3 1 1 2
Push Number+1
Stack ' 5 4 4 4 4 3 3 1 1 2
Shift Stack.size-5,-2
Stack ' 3 4 5 4 4 4 3 1 1 2 
Shift Stack.size-1,2
Stack ' 1 2 3 4 5 4 4 4 3 1
Shift 1,-4
Stack' 4 3 2 1 5 4 4 4 3 1
ShiftBack stack.size-3, -stack.size
Stack '5 4 4 4 3 1 1 2 3 4
Drop 6
Stack ' 1 2 3 4
ShiftBack 3,2
Stack ' 3 4 1 2
Shift3, 2    ' reverse of ShiftBack 3, 2
Stack ' 1 2 3 4



Τρίτη 12 Μαρτίου 2019

Σύντομος οδηγός της Μ2000

Μόλις τελείωσε ο Σύντομος Οδηγός της Μ2000

Υπάρχει και σε epub εδώ  (μικρότερο αρχείο).
Είναι μόλις 56 σελίδες (πιο σύντομος δεν γίνεται), χωρίς να αναλύει όλες τις αριθμητικές και αλφαριθμητικές συναρτήσεις (υπάρχει ενσωματωμένη βοήθεια). Είναι πιο σύντομος από το Μικρό Εγχειρίδιο και σαφώς πιο μικρός από το online εγχειρίδιο των 35 τευχών.

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


Αναθεώρηση 13 Έκδοση 9.8

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

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


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

Και αυτή η αναθεώρηση έχει να κάνει με το ελληνικό λεξιλόγιο. Όταν ορίζουμε τύπο παραμέτρου σε συνάρτηση ή σε τμήμα "ως σωρός" τώρα δουλεύει (πριν δούλευε μόνο με το as stack στα αγγλικά).



Δευτέρα 11 Μαρτίου 2019

Αναθεώρηση 11 Έκδοση 9.8

Ένα σφάλμα διορθώθηκε στην ΑΛΛΙΩΣ στην δομή επιλογής ΑΝ, στην διαμόρφωση σε πολλές γραμμές χωρίς χρήση μπλοκ.
Στο παρακάτω μόλις έφτανε η ροή στο Αλλιώς αντί να κοιτάει για την Τέλος Αν έψαχνε για την End If. Τώρα λειτουργεί σωστά!

(το ? είναι η Τύπωσε σε συντομογραφία).

Αν Αληθές τότε
    Αν Αληθές τότε
        ? 1
    Τέλος Αν
Αλλιώς
    Αν Αληθές Τότε
        ? 2
    Τέλος Αν
Τέλος Αν

Σάββατο 9 Μαρτίου 2019

Αναθεώρηση 8 έκδοση 9.8

Προσθήκη 2-12-2021
Στην Έκδοση 10, υπάρχει στο info αρχείο το τμήμα ΓΛΩΣΣΑ με πιο προχωρημένο κώδικα, με διάφανο τίτλο και μενού (combobox), με χρωματισμό της γραμμής που έχει το δρομέα, με χρώμα επιλεγμένο για την κάθετη μπάρα ολίσθησης (η οποία κρύβεται αυτόματα). Επίσης με μενού αναδυόμενο (popup) στη θέση του δρομέα με δυνατότητα να γράψουμε τον αριθμό γραμμής και να μεταφέρουμε το δρομέα εκεί! Επίσης υπάρχει και ένα Button που λειτουργεί μόνο ως ένδειξη μηνυμάτων δεξιά από το μενού, και δείχνει τη γραμμή και θέση του δρομέα με αριθμούς. Στο μενού επεξεργασία υπάρχει και το άνοιγμα στον διερμηνευτή της γλώσσας (αν είναι εγκατεστημένος, ανοίγει το πρόγραμμα εκεί για εκτέλεση). Στη βοήθεια αλλάζουμε τη προβολή, Μεγάλα ή Μικρά. Επίσης στο παράδειγμα αυτό δείχνω πως αλλάζουμε το μέγεθος γραμμάτων και γραμματοσειρά στον τίτλο της φόρμας! Δείτε επίσης πάνω αριστερά πως έχει μπει εικονίδιο και ότι υπάρχει ένα κουμπί με τρεις γραμμές από όπου δίνουμε εντολές για απόκρυψη (ελαχιστοποίηση) επέκταση (μεγιστοποίηση) και μετακίνηση και αλλαγή μεγέθους με τα πλήκτρα. Το έχω αφήσει επίτηδες έτσι ώστε βλέποντας άλλα προγράμματα μέσα στο Info να μπορεί κανείς να το βελτιώσει, όπως να δει πώς βάζουμε λειτουργία Hover στο μενού, όπου όταν πάμε το δείκτη του ποντικιού πάνω από τα μενού και τα ενεργοποιήσουμε μια φορά, τότε τα μενού ανοίγουν καθώς περνάμε το δείκτη πάνω τους, υπάρχει στο cs τον csharp editor. Επίσης δείτε πώς γίνεται να ορίσουμε Accelerator Keys, υπάρχουν στο mEditor (το οποίο έχει όλα εκτός από το πώς αλλάζουμε τα χρώματα στο EditBox, το οποίο το έχει το cs). Στο info υπάρχουν τέσσερις εκδοχές του NotePad, mEditor (έχει και δεύτερο EditBox για βοήθεια της M2000, κρυφό αρχικά), cs, htmleditor, ΓΛΩΣΣΑ. Το καθένα έχει κάτι διαφορετικό από τα άλλα!





Παλιό Κείμενο (Έκδοση 8, τρέχει και στην 10 - γενικά οι νέες εκδόσεις είναι συμβατές με τις παλιές):
Βελτίωσα τον χρωματιστή κώδικα στο EditBox,
Εδώ είναι το notepad με τις αλλαγές για να χρωματίζει κώδικα σε ΓΛΩΣΣΑ του λυκείου για το μάθημα ΑΕΠΠ.

Σε linux μπορεί κανείς να χρησιμοποιήσει  "DejaVu Sans Mono", 14
Η τελευταία παράμετρος της "FontAttr" είναι τα bold, με true έχουμε bold γράμματα.

\\ notepad
Show
Clear
Flush
Title$="Πρόχειρο Γλώσσας"
Dir User
Title Title$, 0
Declare NotePad Form
Declare Pad EditBox Form NotePad
Declare File1 Combobox Form NotePad
Declare Edit1 Combobox Form NotePad
Declare Help1 Combobox Form NotePad
Method Pad, "FontAttr", "COURIER NEW", 12, false
With Pad, "NoWrap", True, "ColorCollection1", "|ΠΡΟΓΡΑΜΜΑ|ΜΕΤΑΒΛΗΤΕΣ|ΠΡΑΓΜΑΤΙΚΕΣ|ΑΚΕΡΑΙΕΣ|ΛΟΓΙΚΕΣ|ΧΑΡΑΚΤΗΡΕΣ|ΣΤΑΘΕΡΕΣ|ΑΡΧΗ|ΓΡΑΨΕ|ΔΙΑΒΑΣΕ|ΤΕΛΟΣ_ΠΡΟΓΡΑΜΜΑΤΟΣ|DIV|MOD|ΑΝ|ΤΟΤΕ|ΑΛΛΙΩΣ|ΑΛΛΙΩΣ_ΑΝ|ΤΕΛΟΣ_ΑΝ|ΓΙΑ|ΑΠΟ|ΜΕΧΡΙ|ΜΕ_ΒΗΜΑ|ΤΕΛΟΣ_ΕΠΑΝΑΛΗΨΗΣ|ΕΠΙΛΕΞΕ|ΠΕΡΙΠΤΩΣΗ|ΤΕΛΟΣ_ΕΠΙΛΟΓΩΝ|ΟΣΟ|ΕΠΑΝΑΛΑΒΕ|ΑΡΧΗ_ΕΠΑΝΑΛΗΨΗΣ|ΜΕΧΡΙΣ_ΟΤΟΥ|ΚΑΙ|Η|ΟΧΙ|ΑΛΗΘΗΣ|ΨΕΥΔΗΣ|ΚΑΛΕΣΕ|ΔΙΑΔΙΚΑΣΙΑ|ΤΕΛΟΣ_ΔΙΑΔΙΚΑΣΙΑΣ|Α_Μ(|Α_Τ(|Ε|ΕΦ(|ΗΜ(|ΛΟΓ(|ΣΥΝ(|Τ_Ρ(|ΣΥΝΑΡΤΗΣΗ|ΤΕΛΟΣ_ΣΥΝΑΡΤΗΣΗΣ|", "LineComment1", "!!", "OtherSymbols",",≤≥≠", "CommentSymbols", "!", "ComSymbolsWidth", 1, "WordCharRight", " ,[]+-*/)}≤≥≠"+chr$(9), "WordCharleft", " ,[]+*/({≤≥≠"+chr$(9),  "LineComment2",CHR$(0), "StringSep2","'", "AssignSym","<-"
With File1,"label","Αρχείο", "listtext" As list$, "list" As list$() '
With Edit1,"label","Επεξεργασία",  "Mark", Color(255,100,0)
With Help1,"label","Βοήθεια",  "Mark", Color(255,100,0)
With NotePad, "Title" As Caption$, "Visible" As Visible, "TitleHeight" As tHeight, "Sizable", True
With Pad, "Text" As Pad.Text$, "NoColor", False, "ShowAlways", True, "tabwidth",2
Def TitleStr$(a$)=ucase$(left$(a$,1))+mid$(a$,2)
Filename$=Dir$+"νεο.glo"
Caption$=TitleStr$(File.Name$(Filename$)) +" - ΓΛΩΣΣΑ"
Method NotePad,"move", 2000, 4000, 8000, 4000
Layer NotePad {Cls #FFA000}
With File1,"MenuStyle", True, "MenuWidth", 3000 
With Edit1,"MenuStyle", True, "MenuWidth", 3000 
With Help1,"MenuStyle", True, "MenuWidth", 3000 
With File1, "MenuEnabled" As mEnable()
For This {
 mi$="MenuItem"  \\ is a temporary variable only for For This Block
 Method File1, mi$,"Φόρτωσε",True
 Method File1, mi$,"Σώσε",True
 Method File1, mi$,""    \\  only  a line here
 Method File1, mi$,"Κλείσε",True
 Method File1, mi$,"Έξοδος",True
 
 Method Edit1, mi$,"Αποκοπή",True
 Method Edit1, mi$,"Αντιγραφή",True
 Method Edit1, mi$,"Επικόληση",True
 
 Method Help1, mi$,"Περί",True
}
Document BackUp$=""
Pad.Text$=BackUp$
Function Notepad.Unload {
      Keyboard "!"
}
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*100, tHeight
      Method Edit1,"move", twipsX*2+twipsX*100, tHeight,  twipsX*160, tHeight
      Method Help1,"move", twipsX*2+twipsX*260, tHeight,  twipsX*120, tHeight
      If NP.height>2000 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.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"
           }
      End Select
}
Function Pad.PopUp {
      Read Local X, Y
      Method Pad,"PopUpMenu", "",X , Y
}
Function File1.DblClick {
      Read New File1index
      Local cont, cont2, f$, NL$={
      }
      File1index++
      {
      On File1index Goto Open1, Save1, ExitNow, Save2, Unload
      Exitnow:
      Exit
Open1:
      If Pad.Text$<>BackUp$ Then {
            If ask("Save Changes first?",Title$)=1 Then Goto Save1
      }
     Layer NotePad {
           Open.file filename$,"c:\","Φόρτωσε Αρχείο","glo"
     }
     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$)) +" - ΓΛΩΣΣΑ"
           Pad.Text$=BackUp$
           } else Pad.text$="": Clear BackUp$
           Method Pad, "Resize"
      }
      Exit
Save1:
      Layer NotePad {
            Save.As Filename$,"c:\","Σώσε αρχείο","glo"
      }
      if not cont2 then Method Pad,"GetFocus"
      Read f$
      If f$="" Then Exit 
      If lcase$(file.type$(f$))<>"glo" then f$=f$+".glo"
      If Exist(f$) Then  If Ask(NL$+"Overwrite"+NL$+f$,Title$)<>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("Να σωθούν οι αλλαγές;",Title$)=1 Then Goto Save1
      }
      Clear BackUp$
      Pad.Text$=""
      If Cont2 then {
           Method NotePad, "CloseNow"
           Keyboard "!"  \\ to end the loop
      } Else {
            FileName$=Dir$+"νεο.glo"
            Caption$=TitleStr$(File.Name$(Filename$)) +" - ΓΛΩΣΣΑ"
            Method Pad, "Resize"
      }
      Exit
Unload:
      Cont2=True : Goto Save2
      }
}
Function Help1.DblClick {
      Local A, info$
      Info$={
            Πρόχειρο για συγγραφή προγραμμάτων σε ΓΛΩΣΣΑ για το μάθημα της ΑΕΠΠ
            }
      A=Ask(info$,Title$,"","")


}
Call Local Notepad.Resize()


Method NotePad,"Show" ', 1
Every 1000 {
If inkey$<>"" then exit
}
Declare Pad Nothing
Declare NotePad Nothing 
Print "Τέλος"



Εδώ η εικόνα από τη φόρμα:




Ο κώδικας μπορεί να εξαχθεί με αντιγραφή στο πρόχειρο με το χρώμα:

ΠΡΟΓΡΑΜΜΑ ΑΛΦΑ
ΣΤΑΘΕΡΕΣ
  ΜΕΓΙΣΤΟ_ΠΛΗΘΟΣ_ΚΕΛΙΩΝ = 100
  ΜΕΓΙΣΤΟ_ΠΛΗΘΟΣ_ΜΠΛΟΚ = 50
ΜΕΤΑΒΛΗΤΕΣ
  ΑΚΕΡΑΙΕΣ: ΠΙΝ[ΜΕΓΙΣΤΟ_ΠΛΗΘΟΣ_ΚΕΛΙΩΝ], ΜΠΛΟΚ[ΜΕΓΙΣΤΟ_ΠΛΗΘΟΣ_ΜΠΛΟΚ], Ν, Μ
  ΑΚΕΡΑΙΕΣ: Ι, Π, Κ, Λ, Π1
  ΑΚΕΡΑΙΕΣ: ΣΠ[ΜΕΓΙΣΤΟ_ΠΛΗΘΟΣ_ΜΠΛΟΚ*2], ΣΚ[ΜΕΓΙΣΤΟ_ΠΛΗΘΟΣ_ΜΠΛΟΚ*2], ΣΤΟΙΒΑ
  ΑΚΕΡΑΙΕΣ: ΜΗΚΟΣ[ΜΕΓΙΣΤΟ_ΠΛΗΘΟΣ_ΜΠΛΟΚ]
  ΛΟΓΙΚΕΣ: ΣΗΜΑΙΑ
ΑΡΧΗ
  ΑΡΧΗ_ΕΠΑΝΑΛΗΨΗΣ
    ΓΡΑΨΕ "ΔΩΣΕ ΑΡΙΘΜΟ ΚΕΛΙΩΝ:"
    ΔΙΑΒΑΣΕ Ν
  ΜΕΧΡΙΣ_ΟΤΟΥ Ν > 0 ΚΑΙ Ν <= ΜΕΓΙΣΤΟ_ΠΛΗΘΟΣ_ΚΕΛΙΩΝ
  ΑΡΧΗ_ΕΠΑΝΑΛΗΨΗΣ
    ΓΡΑΨΕ "ΔΩΣΕ ΑΡΙΘΜΟ ΜΠΛΟΚ"
    ΔΙΑΒΑΣΕ Μ
  ΜΕΧΡΙΣ_ΟΤΟΥ Μ >= 0 ΚΑΙ Μ <= ΜΕΓΙΣΤΟ_ΠΛΗΘΟΣ_ΜΠΛΟΚ
  ΜΗΚΟΣ[1] <- 0
  ΑΝ Μ > 0 ΤΟΤΕ
    ΓΙΑ Ι ΑΠΟ 1 ΜΕΧΡΙ Μ
      ΓΡΑΨΕ "ΜΕΓΕΘΟΣ ΜΠΛΟΚ:", Ι
      ΔΙΑΒΑΣΕ ΜΠΛΟΚ[Ι]
    ΤΕΛΟΣ_ΕΠΑΝΑΛΗΨΗΣ
    ΜΗΚΟΣ[Μ] <- ΜΠΛΟΚ[Μ]
    ΑΝ Μ > 1 ΤΟΤΕ
      ΓΙΑ Ι ΑΠΟ Μ - 1 ΜΕΧΡΙ 1 ΜΕ_ΒΗΜΑ -1
        ΜΗΚΟΣ[Ι] <- ΜΠΛΟΚ[Ι] + ΜΗΚΟΣ[Ι + 1] + 1
      ΤΕΛΟΣ_ΕΠΑΝΑΛΗΨΗΣ
    ΤΕΛΟΣ_ΑΝ
  ΤΕΛΟΣ_ΑΝ
  ΑΝ ΜΗΚΟΣ[1] > Ν ΤΟΤΕ
    ΓΡΑΨΕ "ΑΔΥΝΑΤΟΝ"
  ΑΛΛΙΩΣ_ΑΝ Μ = 0 ΤΟΤΕ
    ΓΙΑ Ι ΑΠΟ 1 ΜΕΧΡΙ Ν
      ΓΡΑΨΕ 0, "  "
    ΤΕΛΟΣ_ΕΠΑΝΑΛΗΨΗΣ
    ΓΡΑΨΕ
  ΑΛΛΙΩΣ
    ΣΤΟΙΒΑ <- 0
    Π1 <- 0
    Λ <- 0
    ΟΣΟ Π1 <= (Ν - ΜΗΚΟΣ[1]) ΕΠΑΝΑΛΑΒΕ
      Κ <- 0
      Π <- Π1 + 1
      ΓΙΑ Ι ΑΠΟ 1 ΜΕΧΡΙ Ν
        ΠΙΝ[Ι] <- 0
      ΤΕΛΟΣ_ΕΠΑΝΑΛΗΨΗΣ
   
      ΑΡΧΗ_ΕΠΑΝΑΛΗΨΗΣ
        ΟΣΟ Κ < Μ ΕΠΑΝΑΛΑΒΕ
          Κ <- Κ + 1
          Λ <- 0
          ΟΣΟ Λ < ΜΠΛΟΚ[Κ] ΚΑΙ Π <= Ν ΕΠΑΝΑΛΑΒΕ
            Λ <- Λ + 1
            ΠΙΝ[Π] <- 1
            Π <- Π + 1
          ΤΕΛΟΣ_ΕΠΑΝΑΛΗΨΗΣ
          ΑΝ Π < Ν ΤΟΤΕ
            ΠΙΝ[Π] <- 0
            Π <- Π + 1
            ΑΝ Κ < Μ ΤΟΤΕ
              ΑΝ (Π + ΜΗΚΟΣ[Κ + 1]) <= Ν ΤΟΤΕ
                ΣΤΟΙΒΑ <- ΣΤΟΙΒΑ + 1
                ΣΠ[ΣΤΟΙΒΑ] <- Π
                ΣΚ[ΣΤΟΙΒΑ] <- Κ
              ΤΕΛΟΣ_ΑΝ
            ΤΕΛΟΣ_ΑΝ
          ΤΕΛΟΣ_ΑΝ
        ΤΕΛΟΣ_ΕΠΑΝΑΛΗΨΗΣ
     
        ΣΗΜΑΙΑ <- ΑΛΗΘΗΣ
        ΑΝ Λ = ΜΠΛΟΚ[Κ] ΤΟΤΕ
          ΓΙΑ Ι ΑΠΟ 1 ΜΕΧΡΙ Ν
            ΓΡΑΨΕ ΠΙΝ[Ι], "  "
          ΤΕΛΟΣ_ΕΠΑΝΑΛΗΨΗΣ
          ΓΡΑΨΕ
          ΑΝ ΣΤΟΙΒΑ > 0 ΤΟΤΕ
            Π <- ΣΠ[ΣΤΟΙΒΑ]
            Κ <- ΣΚ[ΣΤΟΙΒΑ]
            ΣΤΟΙΒΑ <- ΣΤΟΙΒΑ - 1
            ΓΙΑ Ι ΑΠΟ Π ΜΕΧΡΙ Ν
              ΠΙΝ[Ι] <- 0
            ΤΕΛΟΣ_ΕΠΑΝΑΛΗΨΗΣ
            Π <- Π + 1
            ΑΝ Κ < Μ ΤΟΤΕ
              ΑΝ (Π + ΜΗΚΟΣ[Κ + 1]) <= Ν ΤΟΤΕ
                ΣΤΟΙΒΑ <- ΣΤΟΙΒΑ + 1
                ΣΠ[ΣΤΟΙΒΑ] <- Π
                   ! το ΣΚ[ΣΤΟΙΒΑ]<-Κ δεν το βάζουμε είναι ήδη Κ
              ΤΕΛΟΣ_ΑΝ
            ΤΕΛΟΣ_ΑΝ
            ΣΗΜΑΙΑ <- ΨΕΥΔΗΣ
          ΤΕΛΟΣ_ΑΝ
        ΤΕΛΟΣ_ΑΝ
      ΜΕΧΡΙΣ_ΟΤΟΥ ΣΗΜΑΙΑ = ΑΛΗΘΗΣ
      Π1 <- Π1 + 1
    ΤΕΛΟΣ_ΕΠΑΝΑΛΗΨΗΣ
  ΤΕΛΟΣ_ΑΝ
ΤΕΛΟΣ_ΠΡΟΓΡΑΜΜΑΤΟΣ