## Παρασκευή, 30 Νοεμβρίου 2018

### Αναθεώρηση 17 Έκδοση 9.5

Διορθώθηκε το AYTO η μεταβλητή που δείχνει το αντικείμενο μέσα σε μια ομάδα. Σε ορισμένες περιπτώσεις δεν λειτουργούσε σωστά (όπως σωστά λειτουργούσε στην έκδοση 9.4). Λόγω βελτίωσης του κώδικα, έγινε λάθος και η ειδική συνάρτηση για αυτό δεν είχε ολοκληρωθεί σωστά με συνέπεια ενώ έβρισκε το αντικείμενο δεν το επέστρεφε, και γύρναγε το AYTO ως έχει. Παρόλα αυτά το σύστημα λειτουργούσε στις περισσότερες άλλες περιπτώσεις γιατί όταν γύριζε το ΑΥΤΟ (και όχι το πραγματικό όνομα της ομάδας) άλλες συναρτήσεις το ανέλυαν ξανά και το έβρισκαν! Υποτίθεται ότι η συγκεκριμένη "προβληματική" συνάρτηση έπρεπε αν το έβρισκε νωρίς. Υπήρχε λοιπόν περίπτωση οι άλλες συναρτήσεις να "αδιαφορίσουν" αν το ΑΥΤΟ ήταν μόνο του, και όψι με το όνομα κάποιου μέλους της ομάδας, για παράδειγμα το ΑΥΤΟ.Χ ή .Χ (επειδή συνήθως βάζουμε το .Χ και όχι το ΑΥΤΟ.Χ το σύστημα βρίσκει άμεσα το .Χ παρά τα λάθη της συγκεκριμένης συνάρτησης.
Το βρήκα το λάθος εξετάζοντας παλαιότερα προγράμματα που ήξερα ότι δεν είχαν πρόβλημα! Για να το διορθώσω όμως μου πήρε λίγο χρόνο για να βρω που στο κώδικα ήταν. Κατέφυγα σε μια λύση...που λέει ότι αν έχεις ένα άλλο παλαιότερο κώδικα που δουλεύει φτιάξε ένα αντίγραφο και άρχισε να αλλάζεις συναρτήσεις (δέκα δέκα ας πούμε) μέχρι να σου δείξει το πρόγραμμα σε ποιες έχει θέμα, μετά το βρίσκεις αμέσως!

Το παράδειγμα που τώρα δουλεύει είναι αυτό:
https://georgekarras.blogspot.com/2018/06/queue-with-pointers.html

## Πέμπτη, 29 Νοεμβρίου 2018

### Revision 16 Version 9.5

For these changes I have to change Version. So I think in one or two revisions I have to move to 9.6.

1) Overflow in operators *= += /= -= (for decimals)
check the program with upper limit above 27 . Older revision show wrong results for factorial() (first function)

Function factorial (a) {
def decimal f=1
Flush
{
Loop
if a=0 then exit
f*=a : Push a-1
}
=f
}

Function factorial2 (a as decimal) {
f(1, a)
sub f(b as decimal , a as decimal)
if a=0 then =b : exit
f(a*b, a-1)
end sub
}

For i=1 to 27
? factorial(i), i
? factorial2(i)
next i

2) New IF Then Else in one linew
Previous versions we have to do this (using a block of code between then and Else
If False then { Print "true"} Else Print "false"

We can use If  true Then  If True Then If  True .... which work for one line.
2.1

The same for Else.If so from this revision we can do the old  and the new
this is the old with blocks (we have to use them if we have multiple lines, or nested if)
if false then {
print "ok" : print 12,67, 32 : goto 1000
} else.if false then {
Print "Hello There"
PRINT "OK1"
}  else.if false then {
print "not ok2" : ? 12+12
} else 1000 ' a goto 1000
print "done"
1000 print "1000"

Now for on line we can use it without blocks  Do not use nested if without real blocks like the above.

if true then
print "ok" : print 12,67, 32 : goto 1000
else.if false then
Print "Hello There" : PRINT "OK1"
else.if false then
print "not ok2" : ? 12+12
else  1000 ' a goto 1000
print "done"
1000 print "1000"

2.2
using colon to separate statements. We can use goto inside. This is one line (wrapped)
if true then print "ok" : print 12,67, 32 : goto 1000 else.if false then ? "HELLO THERE": PRINT "OK1" else.if false then print "not ok2" : ? 12+12 else ? "not found"
print "done"
1000 print "1000"

2.3
try these
if  false else if false then ? "ok1" else.if false then print "ok2" else if false then ? "done" else ? "ok3"
if  false else if false then ? "ok1" else.if false then print "ok2" else if true then ? "done" else ? "ok3"
if  false else if false then ? "ok1" else.if true then print "ok2" else if true then ? "done" else ? "ok3"
if  false else if true then ? "ok1" else.if true then print "ok2" else if true then ? "done" else ? "ok3"
if  true else if true then ? "ok1" else.if true then print "ok2" else if true then ? "done" else ? "ok3"

if  true then if false then ? "ok1" else.if false then print "ok2" else if false then ? "done" else ? "ok3"
if  true then if false then ? "ok1" else.if false then print "ok2" else if true then ? "done" else ? "ok3"
if  true then if false then ? "ok1" else.if true then print "ok2" else if true then ? "done" else ? "ok3"
if  true then if true then ? "ok1" else.if true then print "ok2" else if true then ? "done" else ? "ok3"
if  true then if true then ? "ok1" else.if true then print "ok2" else if true then ? "done" else ? "ok3"

## Τετάρτη, 28 Νοεμβρίου 2018

### Dragon Curve

This program written for rosettacode.org.

Use Courier New for Windows OS. Works in linux with Courier. (For the title, see Legend statement)

Use second monitor (if there is no second monitor then open to default).

Module Checkit {
def double angle, d45, d90, change=5000
const sr2 as double= .70710676237
Cls 0
Pen 14
\\ move console full screen to second monitor
Window 12, 1
\\ reduce size (tv as second monitor cut pixels from edges)
Window 12, scale.x*.9, scale.y*.9;
\\ opacity 100%, but for 0 (black is 100%, and we can hit anything under console window)
Desktop 255, 0
\\ M2000 console can divide screen to characters/lines with automatic line space
Form 60, 30
\\ cut the border from window
Form
\\ scale.x and scale.y in twips
\\ all graphic/console commands works for printer also (except for Input)
Move scale.x/2,scale.y/10
\\ outline graphics, here outline text
\\ legend text\$, font, size, angle, justify(2 for center), quality (non zero for antialiasing, works for angle 0), letter spacing.
Color {
Legend "DRAGON CURVE", "Courier New",SCALE.Y/200,0,2, 1, SCALE.X/50
}
angle=0
d45=pi/4
d90=pi/2
Move scale.x/3, scale.y*2/3
bck=point
\\ twipsx is width in twips of pixel. twipsy are height in twips of a pixel
\\ so we use length:twips.x*scale.x/40  or scale.x/40 pixels.
\\ use % for integer - we can omit these, and we get integer by automatic conversion (overflow raise error)
dragon(twipsx*scale.x/40,14%, 1)
Pen 14
a\$=key\$
Cls 5
\\ set opacity to 100%
Desktop 255
End
\\ Subs are private to this module
\\ Subs have same scope as module
Sub turn(rand as double)
angle+=rand
End Sub
\\ angle is absolute, length is relative
Sub forward(length as double)
Draw Angle angle, length
End Sub
Sub dragon(length as double, split as integer, d as double)
If split=0 then {
forward(length)
} else {
Gosub turn(d*d45)
\\ we can omit Gosub
dragon(length*sr2,split-1,1)
turn(-d*d90)
dragon(length*sr2,split-1,-1)
turn(d*d45)
change--
If change else {
push 0: do {drop: push random(11,15) : over } until number<>pen: pen number
change=5000
}
}
End Sub
}
Checkit

## Τρίτη, 27 Νοεμβρίου 2018

### Revision 15 Version 9.5

From rev 15
1. Many fixes for  bugs from changes from past revisions.
Because of a new faster stack object for group internal struture, two properties are forgotten to implement these functions was broken member\$(), member.type\$() and Valid(@GroupobjectA as GroupobjectB). So now these fixed.

global group e {
long alfa=50
dim k%(10)
}
for i=1 to group.count(e) {
Print member\$(e, i),member.type\$(e, i)
}
list

2. Minor works in Forms, especial for modals forms (older versions like 8.2 they work pretty good with this example). We can select XX=0  to open all as non modal.  A modal window disable the user action to form (forms can show anything, and moved also by software). So from this revision also fixed.

\\ An example of modal show
\\ When we open then msgbox we have 5 modal windows,
\\ one after the other, without stopping the background task
\\ Modal Show (with parameter 1), open window disabling others,
\\ but each level of modal window know which window is for enabling again
\\ until we close them
Global XX=1
Declare Simple(5) form
dim Visible(5)
For i=0 to 4
Method Simple(i), "FontAttr", "Arial Black", 18
With Simple(i), "Visible" as Visible(i)
Layer Simple(i) {
Linespace 30
Window 12, 10000,8000
Cls 1,0
Form 30,20 \\ make 30X20 chars*lines calculating new font size.
Cursor 0,3
Print width, height
Print "01234567890123456789"
}
Next i
if XX<>0 then exit
method Simple(index), "Hide"
cancel=true
}

k=0
\\ this is the background task
k++
Print k
refresh
} As anything

Function simple.click {
Select Case index
Case 0
{
After 50 {
Method Simple(1), "Show" , XX
Layer { Print "end case 0" }
}
}
Case 1
{
After 50 {
Method Simple(2), "Show" , XX
Layer { Print "end case 1" }
}
}
Case 2
{
After 50 {
Method Simple(3), "Show" , XX
Layer { Print "end case 2" }
}
}
Case 3
{
After 50 {
Method Simple(4), "Show" , XX
Layer { Print "end case 3" }
}
}
Case 4
{
after 500 {
Layer { Print "end case 4" }
}
}
End Select
}
Print visible(0), visible(1),visible(2), visible(3), visible(4)
If visible(0)=0 then thread this erase
refresh
} as main

After 500 {
Method Simple(0), "Show", 1
}
wait 1000
A\$=Key\$

Print "Finish"
Declare simple() Nothing
Show  \\ set focus to M2000 console

3) New Type\$(). Rewrite Type\$() to handle array and inventory items too. Also we can set a path to inner objects. Some peculiar things with new revision.

group beta {
x\$="1000mm"
m=100
}
\\  beta copied here
inventory alfa=1:=(list:=1,2,300:=(1,2,3,3,5,beta), 500:="ok")

dim g()
\\  beta copied here
g()=(100,beta,(1, (list:=1:=beta,2,"z":=(1,200,3,alfa), "s":="string"), "Hello there"), 500@, "ok")
g(1).m*=100
Print g(1).m=10000
Print type\$(g(2), 1)="Inventory"
Print type\$(g(2), 1!)="List"   ' show type of inventory (list or queue)
Print type\$(g(2), 2)="String", g(2)#val\$(2)="Hello there"
Print g\$(2)(2)="Hello there"    ' using g\$() a reference to g()
Print g\$(2)(1)("s")="string"
Print g\$(2)(1)("z")(3)(1)(500)="ok"
\\ new this also
Print  g(2)(1)("z")(3)(1)(300)(5).m=100 ' multiple object opening until a group object
\\ new this also. we can get a pointer from inner group
n->g(2)(1)("z")(3)(1)(300)(5)
Print n=>m=100
n=>m++ ' increment one
Print g(2)(1)("z")(3)(1)(300)(5).m=101
Print g(2)(1)("z")(3)(1)(300)(5).x\$="1000mm"
n=>x\$="2000mm"
Print g(2)(1)("z")(3)(1)(300)(5).x\$="2000mm"
m=g() ' we get a pointer to array ' these are not the same as the group's pointers
\\ stacks, inventories and arrays (not those we make with Dim) are pointers
\\ we can use IS operator to check two of them if show same object
z=list:=100, 150:=m, 200
Print z(150)(2)(1)("z")(3)(1)(300)(5).m=101
\\ using g() we pass a copy
\\ but anything which is a pointer (like a list, or a pointer to array) only pointer copied
\\ groups may have or may haven't pointers. Those with no pointers copied when we get an array copy.
\\ Only arrays with names with parenthesis copied. So here we get a copy of g().
z=list:=100, 150:=g(), 200
g(1).m+=100
Print g(1).m=10100
Print z(150)(2)(1)("z")(3)(1)(300)(5).m=101 ' group has a pointer/ also list is the same
Print z(150)(1).m=10000 ' group copied
n=>m++
Print z(150)(2)(1)("z")(3)(1)(300)(5).m=102
Print g(2)(1)("z")(3)(1)(300)(5).m=102

From rev 14

1) Fix for expression evaluator, from last revision (rev.14).

2) Addition for URL encoding/decoding and parsing (introduced in rev. 14 fixed in rev. 15)

Stack New {
Data "foo://example.com:8042/over/there?name=ferret#nose", "urn:example:animal:ferret:nose"
Data "jdbc:mysql://test_user:ouupppssss@localhost:3306/sakila?profileSQL=true", "ftp://ftp.is.co.za/rfc/rfc1808.txt"
Data "mailto:John.Doe@example.com", "news:comp.infosystems.www.servers.unix", "tel:+1-816-555-1212"
Data "telnet://192.0.2.16:80/", "urn:oasis:names:specification:docbook:dtd:xml:4.1.2", "ssh://alice@example.com"
Data "https://bob:pass@example.com/place", "http://example.com/?a=1&b=2+2&c=3&c=4&d=%65%6e%63%6F%64%65%64"
a=Array([])
}
function prechar\$(a\$, b\$) {
if a\$<>"" then {=quote\$(b\$+a\$)} else ={""}
}
z=each(a)
document s\$="["+{
}
While z {
a\$=array\$(z)
s1\$={           "uri": }+quote\$(a\$)+{,
"authority": }+ quote\$(string\$(a\$ as URLAuthority))+{,
"userInfo": }+ quote\$(string\$(a\$ as URLUserInfo))+{,
"scheme": }+quote\$(string\$(a\$ as URLScheme))+{,
"hostname": }+quote\$(string\$(a\$ as UrlHost))+{,
"Port": }+quote\$(string\$(a\$ as UrlPort))+{,
"pathname": }+quote\$(string\$(a\$ as UrlPath))+{,
"search": }+prechar\$(string\$(a\$ as URLpart 6),"?")+{,
"hash": }+prechar\$(string\$(a\$ as UrlFragment),"#")+{
}
s\$="     {"+{
}+s1\$+"     }"
if z^<len(a)-1 then s\$=" ,"   ' append to document
s\$={
}
}
s\$="]"
Report s\$

Ouput:

[
{
"uri": "foo://example.com:8042/over/there?name=ferret#nose",
"authority": "example.com:8042",
"userInfo": "",
"scheme": "foo",
"hostname": "example.com",
"Port": "8042",
"pathname": "/over/there",
"search": "?name=ferret",
"hash": "#nose"
} ,
{
"uri": "urn:example:animal:ferret:nose",
"authority": "",
"userInfo": "",
"scheme": "urn",
"hostname": "",
"Port": "",
"pathname": "example:animal:ferret:nose",
"search": "",
"hash": ""
} ,
{
"uri": "jdbc:mysql://test_user:ouupppssss@localhost:3306/sakila?profileSQL=true",
"authority": "",
"userInfo": "",
"scheme": "jdbc",
"hostname": "",
"Port": "",
"pathname": "mysql://test_user:ouupppssss@localhost:3306/sakila",
"search": "?profileSQL=true",
"hash": ""
} ,
{
"uri": "ftp://ftp.is.co.za/rfc/rfc1808.txt",
"authority": "ftp.is.co.za",
"userInfo": "",
"scheme": "ftp",
"hostname": "ftp.is.co.za",
"Port": "21",
"pathname": "/rfc/rfc1808.txt",
"search": "",
"hash": ""
} ,
{
"authority": "www.ietf.org",
"userInfo": "",
"scheme": "http",
"hostname": "www.ietf.org",
"Port": "80",
"pathname": "/rfc/rfc2396.txt",
"search": "",
} ,
{
"uri": "ldap://[2001:db8::7]/c=GB?objectClass=one&objectClass=two",
"authority": "2001:db8::7",
"userInfo": "",
"scheme": "ldap",
"hostname": "2001:db8::7",
"Port": "389",
"pathname": "/c=GB",
"search": "?objectClass=one&objectClass=two",
"hash": ""
} ,
{
"uri": "mailto:John.Doe@example.com",
"authority": "",
"userInfo": "",
"scheme": "mailto",
"hostname": "",
"Port": "",
"pathname": "John.Doe@example.com",
"search": "",
"hash": ""
} ,
{
"uri": "news:comp.infosystems.www.servers.unix",
"authority": "",
"userInfo": "",
"scheme": "news",
"hostname": "",
"Port": "",
"pathname": "comp.infosystems.www.servers.unix",
"search": "",
"hash": ""
} ,
{
"uri": "tel:+1-816-555-1212",
"authority": "",
"userInfo": "",
"scheme": "tel",
"hostname": "",
"Port": "",
"pathname": "+1-816-555-1212",
"search": "",
"hash": ""
} ,
{
"uri": "telnet://192.0.2.16:80/",
"authority": "192.0.2.16:80",
"userInfo": "",
"scheme": "telnet",
"hostname": "192.0.2.16",
"Port": "80",
"pathname": "",
"search": "",
"hash": ""
} ,
{
"uri": "urn:oasis:names:specification:docbook:dtd:xml:4.1.2",
"authority": "",
"userInfo": "",
"scheme": "urn",
"hostname": "",
"Port": "",
"pathname": "oasis:names:specification:docbook:dtd:xml:4.1.2",
"search": "",
"hash": ""
} ,
{
"uri": "ssh://alice@example.com",
"authority": "alice@example.com",
"userInfo": "alice",
"scheme": "ssh",
"hostname": "example.com",
"Port": "",
"pathname": "",
"search": "",
"hash": ""
} ,
{
"uri": "https://bob:pass@example.com/place",
"authority": "bob:pass@example.com",
"userInfo": "bob:pass",
"scheme": "https",
"hostname": "example.com",
"Port": "443",
"pathname": "/place",
"search": "",
"hash": ""
} ,
{
"uri": "http://example.com/?a=1&b=2+2&c=3&c=4&d=%65%6e%63%6F%64%65%64",
"authority": "example.com",
"userInfo": "",
"scheme": "http",
"hostname": "example.com",
"Port": "80",
"pathname": "/",
"search": "?a=1&b=2+2&c=3&c=4&d=%65%6e%63%6F%64%65%64",
"hash": ""
}
]

## Σάββατο, 24 Νοεμβρίου 2018

### Revision 13 Version 9.5

Fix a small bug: Test this lin  x=(1,2,3,4,5) : Print x#max()-x#min()

Module Pairs {
\\ written in version 9.5 rev. 13
\\ use Gdi+ antialiasing (not work with Wine in Linux, but we get no error)
smooth on
Const center=2, right=3, left=1, blue=1, angle=0, dotline=3
Const size9pt=9, size11pt=11
Cls ,0 ' use current background color, set split screen from line 0
Cursor 0,3
Report center, "Coordinate pairs"
x = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
y = (2.7, 2.8, 31.4, 38.1, 58.0, 76.2, 100.5, 130.0, 149.3, 180.0)
dx=scale.x/2/len(x)
dy=dx 'ratio 1:1
graH=dy*len(x)
Basex=scale.x/4
Basey=(scale.y+graH)/2
Move Basex, Basey
\\ draw use relative coordinates
Draw 0,-graH
\\ Step just move graphic cursor
Step 0, graH
Draw scale.x/2
Step -scale.x/2
\\ scX is 1, not used
max=Y#max()
\\ Auto scale for Y, using 0 for start of axis Y
scY=-graH/((max+5^log(max) ) div 100)/100
\\ make vertical axis using dots with numbers center per dx
j=1
For i=basex+dx to basex+dx*x#max() Step dx
Move i, basey
Step 0, twipsy*10
Legend format\$("{0}",array(x,j)), "courier", size9pt, angle, center
Width 1, dotline { draw 0, -graH-twipsy*10,7}
j++
Next i
\\ the same for horizontal axis
HalfTextHeight=Size.y("1","courier", size9pt)/2
For i=basey-dy to basey-dy*x#max() Step dy
Move basex, i
Step -twipsx*10
Width 1, dotline { draw scale.x/2+twipsx*10,,7}
Move basex-100, i+HalfTextHeight
Legend format\$("{0}",(i-basey)/scY), "courier", size9pt, angle, left
Next i
ex=each(x) : ey=each(y)
\\ start from first point. We use Draw to for absolute coordinates
Move array(x,0)*dx+Basex, array(y,0)*scy+Basey
While ex, ey {
Width 2 {
Draw to array(ex)*dx+Basex, array(ey)*scy+Basey, blue
}
}
\\ second pass for marks and labels
ex=each(x) : ey=each(y)
While ex, ey {
Move array(ex)*dx+Basex, array(ey)*scy+Basey
Step -75, -75
Pen 12 {draw 150: draw 0,150 : draw -150 : draw 0,-150}
Pen 13 {
Step 200, -200
Legend format\$("({0}-{1})",array(ex),array(ey) ), "courier bold", size11pt, angle, right
}
}
\\ screenshot to clipboard
Screenshot\$=""
Move 0,0
Copy scale.x, scale.y to Screenshot\$
Clipboard Screenshot\$
a\$=key\$
}
Pairs