Skip to content

Releases: M2000Interpreter/Environment

Version 14 Revision 46

03 Jun 15:35

Choose a tag to compare

SHA 256 294bfd9b05060cf7213d9801a851c689293a9080a4c2b4318ff0c9f5e2bde550

A big fault when using after AND/OR/XOR/NOT two or more strings and then comparison operator. Now is ok.
Test Example:

a$="aa" ' same without suffix $
b$="bb" ' same without suffix $

' these was ok:
if a$+b$="aabb" then print "ok 1"
if "aabb"=a$+b$ and a$<>b$ then print "ok 2"
if a$+b$="aabb" and a$<>b$ then print "ok 3"
if a$<>b$ and "aabb"=a$+b$ then print "ok 4"

' this was wrong:
if a$<>b$ and a$+b$="aabb" then print "ok 5"

' these was ok:

if (a$+b$="aabb") then print "ok 1-1"
if ("aabb"=a$+b$) and a$<>b$ then print "ok 2-1"
if (a$+b$="aabb") and a$<>b$ then print "ok 3-1"
if a$<>b$ and ("aabb"=a$+b$) then print "ok 4-1"

' this was wrong:
if a$<>b$ and (a$+b$="aabb") then print "ok 5-1"

' this was wrong:
if not a$+b$="aabb" then print "ok 1-2"

' these was ok:
if "aabb"=a$+b$ and not a$=b$ then print "ok 2-2"
if a$+b$="aabb" and not a$=b$ then print "ok 3-2"
if a$<>b$ and not "aabb"<>a$+b$ then print "ok 4-2"

' this was wrong:
if a$<>b$ and not a$+b$<>"aabb" then print "ok 5-2"

? "Without suffix $ - these are different variables"
a="aa"
b="bb"

' these was ok:
if a+b="aabb" then print "ok 1"
if "aabb"=a+b and a<>b then print "ok 2"
if a+b="aabb" and a<>b then print "ok 3"
if a<>b and "aabb"=a+b then print "ok 4"

' this was wrong:
if a<>b and a+b="aabb" then print "ok 5"

' these was ok:

if (a+b="aabb") then print "ok 1-1"
if ("aabb"=a+b) and a<>b then print "ok 2-1"
if (a+b="aabb") and a<>b then print "ok 3-1"
if a<>b and ("aabb"=a+b) then print "ok 4-1"

' this was wrong:
if a<>b and (a+b="aabb") then print "ok 5-1"

' this was wrong:
if not a+b="aabb" then print "ok 1-2"

' these was ok:
if "aabb"=a+b and not a=b then print "ok 2-2"
if a+b="aabb" and not a=b then print "ok 3-2"
if a<>b and not "aabb"<>a+b then print "ok 4-2"

' this was wrong:
if a<>b and not a+b<>"aabb" then print "ok 5-2"

Version 14 Revision 45

  1. A Book for OOP for Greek Language plus all programs (97)of book in one module, as oop97.gsb
  2. A tiny fix:

Class Alfa {
Private:
	{read z as double}
	k=z
Public:
	value (n) {=n*.k}
}
M=Alfa(100)
Print M(3)=300
Print Eval(M, 3)=300 ' <<< this fixed

Version 14 Revision 44
I fixed an error from revision 40. I forgot to fix Interpreter for constant objects and a lambda function. The Interpreter finds the constant (is an object of type constant) and then uses this object to pass arguments x, y to the default property. That is fault. So, I changed it, so now Interpret skips this object and then find the function L() and we get the result as expected. Previous revisions are ok because they did nothing for any object, except the Inventory object.

This is the code:
Const L=Lambda (x, y)->x^y
Print L(2,3)=8 ' here was the error

Version 14 Revision 43
Fix the Select Case: One problem was the Case and Με (greek version) using semi boolean like <50 which interpreter before the fix saw this as a variable with the start of an operator. The second problem was an error on End Select with a fault for an inner select case at the last case - case else or else case (both works).

tuple=(100, 200, 77, 500, 1005, -20, 75, 90)
Case=100  ' this is a variable
for i=1 to 100
    x=tuple#Val(Random(0,7))
    LIST
    Print "x=";x
    Select Case x
    Case 100, 200
        Print "One line1"
        Print "One line2"
    Case 1000, 500
        x+=10
    Case <50
    {
        x++
    }
    Case 70 έως 80
        Select Case x
        Case 73
            x/=10
        Case Else
            x|Υπόλ 10
        End Select
    Case Else
        x-=50
    End Select
    Print "Export x=";x, Case=100, i
next 

This is the Greek Version:

Π=(100, 200, 77, 500, 1005, -20, 75, 90)
Για ι=1 εως 100
    Με=100
    Χ=Π#Τιμή(Τυχαίος(0,7))
    Λίστα	
    Τύπωσε "Χ=";Χ
    Επίλεξε Με Χ
    Με 100, 200
        Τύπωσε "Σε μια γραμμή1"
        Τύπωσε "Σε μια γραμμή2"
    Με 1000, 500
      	Χ+=10
    Με <50
    {
        Χ++
    }
    Με 70 έως 80
      	Επίλεξε Με Χ
      	Με 73
            Χ/=10
        Με Αλλιώς
            Χ|Υπόλ 10
        Τέλος Επιλογής
    Με Αλλιώς
        Χ-=50
    Τέλος Επιλογής
    Τύπωσε "Εξαγωγή Χ=";Χ, Με=100, ι
Επόμενο

Version 14 Revision 42
See Readme.txt
Help now has VARPTR() also (and an example for making the STRPTR())

With English staments:

Declare Peek.Long lib "msvbvm60.GetMem4" {Long addr, Long retValue}
Declare Peek.Integer lib "msvbvm60.GetMem2" {Long addr, Long retValue}
Declare Peek.Byte lib "msvbvm60.GetMem1" {Long addr, Long retValue}

Integer ret : Long ret2, there: Byte Ret3
If Locale=1032 then
	Const frm="###,### \Ψ\η\φ\ί\α"
else
	Const frm="###,### \B\y\t\e\s"
end if
a$="alfa12345"
Print str$(Len(a$)*2, frm)
there=StrPtr(VarPtr(a$))
hex "StrPtr:";there
If there>0 then
		Call Peek.Long there-4, varptr(ret2)
		Print "bytes=";ret2
		For n=0 to (ret2-1) div 2
			Call Peek.Integer there, varptr(ret)
			there+=2
			Print chrcode$(ret);
		Next
	Print
end if
Print str$(Len(String$(a$, 2000000))*2, frm)
there=StrPtr(VarPtr(a$))
hex "StrPtr:";there
a$=str$("alfa12345")
Print str$(Len(a$)*2, frm)

there=StrPtr(VarPtr(a$))
hex "StrPtr:";there
If there>0 then
		Call Peek.Long there-4, varptr(ret2)
		Print "bytes=";ret2
		For n=0 to ret2-1
			Call Peek.Byte there, varptr(ret3)
			there++
			Print chr$(ret3);
		Next
	Print
end if
Print str$(Len(String$(a$, 2000000))*2, frm)
there=StrPtr(VarPtr(a$))
hex "StrPtr:";there

function StrPtr(varptr as Long)
	Local thatptr as Long
	Call Peek.Long varptr, varptr(thatptr)
	=thatptr
end function

Slight different (using constant values) for the Greek version:

Όρισε Πάρε.Μακρύ Από "msvbvm60.GetMem4" {Μακρύς διεύθυνση, Μακρύς διεύθυνση_μεταβλητής}
Όρισε Πάρε.Ακέραιο Από "msvbvm60.GetMem2" {Μακρύς διεύθυνση, Μακρύς διεύθυνση_μεταβλητής}
Όρισε Πάρε.Ψηφίο Από "msvbvm60.GetMem1" {Μακρύς διεύθυνση, Μακρύς διεύθυνση_μεταβλητής}

Ακέραιος Επ1 : Μακρύς Επ2, Δείκτης_Στο_Χαρακτήρα: Ψηφίο Επ3
Σταθερές Δεικτ="Δείκτης Στο Πρώτο Χαρακτήρα:",
         Ψηφ="Ψηφία (αριθμός καταχωρημένος στο αλφαριθμητικό):",
         Δείγμα="Alfa12345"
 
Αν Τοπικό=1032 Τότε
	Σταθερή φόρμα_αριθμού="###,### \Ψ\η\φ\ί\α"
Αλλιώς
	Σταθερή φόρμα_αριθμού="###,### \B\y\t\e\s"
Τέλος Αν
α$=Δείγμα
Τύπωσε Γραφή$(Μήκος(α$)*2, φόρμα_αριθμού)
Δείκτης_Στο_Χαρακτήρα=ΔείκτηςΑλφ(ΔιευθΜ(α$))
Δεκαεξ Δεικτ;Δείκτης_Στο_Χαρακτήρα
Αν Δείκτης_Στο_Χαρακτήρα>0 Τότε
		Κάλεσε Πάρε.Μακρύ Δείκτης_Στο_Χαρακτήρα-4, ΔιευθΜ(Επ2)
		Τύπωσε Ψηφ;Επ2
		Για ν=0 έως (Επ2-1) δια 2
			Κάλεσε Πάρε.Ακέραιο Δείκτης_Στο_Χαρακτήρα, ΔιευθΜ(Επ1)
			Δείκτης_Στο_Χαρακτήρα+=2
			Τύπωσε ΧαρΚωδ$(Επ1);
		Επόμενο
	Τύπωσε
Τέλος Αν
Τύπωσε Γραφή$(Μήκος(Επαν$(α$, 2000000))*2, φόρμα_αριθμού)
Δείκτης_Στο_Χαρακτήρα=ΔείκτηςΑλφ(ΔιευθΜ(α$))
Δεκαεξ Δεικτ;Δείκτης_Στο_Χαρακτήρα
α$=Γραφή$(Δείγμα)
Τύπωσε Γραφή$(Μήκος(α$)*2, φόρμα_αριθμού)

Δείκτης_Στο_Χαρακτήρα=ΔείκτηςΑλφ(ΔιευθΜ(α$))
Δεκαεξ Δεικτ;Δείκτης_Στο_Χαρακτήρα
Αν Δείκτης_Στο_Χαρακτήρα>0 Τότε
		Κάλεσε Πάρε.Μακρύ Δείκτης_Στο_Χαρακτήρα-4, ΔιευθΜ(Επ2)
		Τύπωσε Ψηφ;Επ2
		Για ν=0 έως Επ2-1
			Κάλεσε Πάρε.Ψηφίο Δείκτης_Στο_Χαρακτήρα, ΔιευθΜ(Επ3)
			Δείκτης_Στο_Χαρακτήρα++
			Τύπωσε χαρ$(Επ3);
		Επόμενο
	Τύπωσε
Τέλος Αν
Τύπωσε Γραφή$(Μήκος(Επαν$(α$, 2000000))*2, φόρμα_αριθμού)
Δείκτης_Στο_Χαρακτήρα=ΔείκτηςΑλφ(ΔιευθΜ(α$))
Δεκαεξ Δεικτ;Δείκτης_Στο_Χαρακτήρα

Συνάρτηση ΔείκτηςΑλφ(Διεύθ_Μεταβλητής ως Μακρύς)
	Τοπική οΔείκτης ως Μακρύς
	Κάλεσε Πάρε.Μακρύ Διεύθ_Μεταβλητής, ΔιευθΜ(οΔείκτης)
	=οΔείκτης
Τέλος Συνάρτησης

Last example for BigIntegers used as List Keys:

' using Bigintegers for keys
' keys are always strings
' Bigintegers convert to Base10 strings as keys
inventory list1
z=1312_3123_0000_0000_12345u
z1=9_3123_0000_0000_12345u
? z, "&&&&"
list1(z)=1000
z++
Append List1, z:=2000, z1:=6000
z--
Return List1, z:=1500
z+=10
list1(z)=3000
z-=10
? z, "????"
Delete list1, z
z++
Print list1(z)
sort descending list1 as number
m=each(List1)
while m
	? eval$(M!), eval(M) ' key value pair
end while

sort ascending list1 as number
m=each(List1)
while m
	? eval$(M!), eval(M)
end while
' reverse iteration
m=each(List1, -1, 1)
while m
	? eval$(M!), eval(M)
end while
Print Exist(List1, z)

Version 14 Revision 41

I do plenty of work this is some of:

  1. Fix a hidden bug:
    This example now work without error in module ALFA.
MODULE ALFA {
	TRY {
		PROBLEM("GEORGE", 12123)
	}
	PRINT ERROR$
	// PROBLEM START FROM THE READ AT SUB PARAMETER LIST
	SUB PROBLEM(THAT AS VARIANT="")
		PRINT THAT
		READ THAT  ' HERE WAS THE PROBLEM
		PRINT THAT
	END SUB
}
ALFA
MODULE ALFA1 {
	PROBLEM("GEORGE", 12123)
	SUB PROBLEM()
		' NO PROBLEM BECAUSE THIS IS THE GENERIC READ
		READ THAT AS VARIANT=""
		PRINT THAT
		READ THAT  ' HERE WAS THE PROBLEM
		PRINT THAT
	END SUB
}
ALFA1

  1. Fix a problem with Continue inside then else without block - worked as restart so never go to actual block for/next
aa=0
for i=1 to 100
	if i<3 then continue else aa++
next
print aa=98

  1. Now we get true from the last print (?)
a=("aa",2,3,"hello",5)
link a to a$()
try {
	a$(0)="???"
}
? a$(0)="???"  ' true

  1. When we use Ctrl+C (copy to clipboard) in EditBox and Editor (as text editors) then we get visual message that the copy to clipboard done (sometimes I press light the C so I was thing that the copy done, but that not happen, so I insert the message to take knowledge about my difficulty...Also I have a lot this year I become 60 years old).
    Also I fix the search with F2 (up), now works as expected. (F3 down was ok).

  2. We can use STATIC SUB to inform Interpreter for subs before we use them. This it the code fr...

Read more

Version 14 Revision 40

19 May 09:20

Choose a tag to compare

SHA 256 370e5d1023eda4c5b49a167b004ff40d00c5c94598bdc838d8db11a403489440

  1. Fix Modules ? "sreach" ' was a mistake from some revisions before - although Modules ? "","alfa|beta" was ok
  2. Some minor fixes (undocument GetObject())
  3. Some major additions: We can use => to address objects (like dot). Works for properties, methods but bot for functions. For functions we can use the same way we use for indexes for properties or we have to use Method which can use buy reference arguments and named arguments. Also method use As for writing the result and can use WITHEVENTS AS name, which make event object for the object which we get as result.

See the example below: Cells is variable which hold two things: The App (Excel.Application) and then number of Cells property. We can use the value of Cells(1,1) or the range (object) as Cells(1,1)^
Also we can use Cells=>item(1,1)=>value so Print Cells(1,1) = Cells=>item(1,1)=>value print True

//	Declare WithEvents App "Excel.Application" 
App = GetObject("", "Excel.Application")
Print type$(App)
WorkBooks=App=>WorkBooks
Print "Books:";WorkBooks=>count
If WorkBooks=>count=0 Then WorkBooks=>Add  ' same as Method WorkBooks, "Add"
Print "Books:";WorkBooks=>count
ActiveWorkBook=App=>ActiveWorkBook
ActiveSheet=App=>ActiveSheet
' App=>Cells(1,1)=12312.4   ' same as the next statement
App=>Cells(1,1)=>value=12312.4
' we get the Cells object which is a range
Cells=App=>Cells
Print Cells(1,1) = Cells=>item(1,1)=>value
Print Cells(1,1) = Cells=>item(1,1)
Print Type$(Cells(1,1)^)="Range"
Cells(1,2)="=A1*100"
Print Cells(1,1)
' there is no SET in M2000
' so we get the object (to not get the default property using ^
range1=Cells(1,1)^
Print range1=>Address="$A$1", Cells(1,1)=>Address="$A$1" 
Print Type$(Cells(1,2))="Double", Type$(Cells(1,2)^)="Range" 
Print Cells(1,2)=>Address
Print Cells(1,2)=>formula
Print Cells(1,2)=>value
ActiveWorkBook=>Saved=True
wait 400
App=>quit

Second Example:

if exist("mytest.xlsx") then
	WorkBook=GetObject("mytest.xlsx")
	App=WorkBook=>Parent : Print type$(App)
	WorkBook=>ActiveSheet=>Cells(1,1)=>value=12312.4
	Cells=WorkBook=>ActiveSheet=>Cells
	print Cells(1,1)=12312.4, Cells(1,1)=>Address="$A$1"
	Range=Cells(1,1)^   ' this is like Set Range=Cells(1,1) - M2000 has no a SET for objects
	print Range=>value=12312.4, Range=>Address="$A$1"
	WorkBook=>Saved=True
	wait 400
	App=>quit
end if

Version 14 Revision 39
Restore Modules ? "partofname" search for modules in memory functionality

Version 14 Revision 38

  1. fix an error which occurs from revision 36 (for 36 to 37).
variant z
long k[10]
z=(1,2,3)
z=k  ' this raise error (revision 36 and 37)

  1. Variables for Complex numbers do not have ++, --, += ... operators. For tuple the operator repeated all items but skipped complex items. For arrays with parenthesis now return error message "wrong operator". Before was an exception on the code and returned "type mismatch".
a=((1,-1i), (2,3i))
a++  ' no message - for complex ++ not work
link a to a()
a(0)++  ' wrong operator ' before was type mismatch a VB6 error.

  1. Fix Variant z=Expr ret object, old workout was to split to two statements: variant z: z=Expr ret object. Example shows variant z to get a group. Because z is variant when we pass a copy of a pointer to group if we use =, so first time variant z=alfa() gets a copy of a pointer. This example shows when each object is destroyed and count the number of objects destroyed.
global counter=1
module tst {
	class alfa {
		x=10
		remove {
			print "deleted ", counter
			counter++
		}
	}
	dim a(10)<<alfa() '' 10 objects
	variant z=alfa() ' now work - before need variant z: z=alfa()
	' 11 objects
	print z=>x=10  ' z is a pointer to alfa
	z->a(4)  'get a pointer of a(4) ' z=a(4) get a pointer of a copy
	z=>x+=100
	? z=>x=110
	? a(4).x=110
	' z is variant - can't hold a named group
	' 12 objects
	z=a(5)  ' get a copy as a pointer to group
	z=>x+=100
	? z=>x=110
	? a(5).x=10
	b=alfa()  ' b is a named group
	' 13 objects = z has a new object
	z=b ' get a pointer to a copy of b
	b.x+=1000
	? b.x=1010
	? z=>x=10
	' z get a pointer to b (as a weak reference not a real pointer)
	z->b
	b.x+=1000   ' b.x = 2010
	? z=>x=2010
	clear b  ' to execute remove part
}
tst

Version 14 Revision 37

  1. A fault index send value a(2)+a(1) to a(1) not a(3). Now fixed
a=list:= 0:=0, 1:=1, 2:=2
a(3)=a(2)+a(1)
? a(3)=3
  1. fix the algorithm for finding the type of text file. A problem was about unicode without BOM UTF16 (LE or BE) vs ANSI.
    The problem was for ANSI file which the system open using Edit or Load.Doc and some time read it as UTF16LE.
    There is a new module in INFO.gsb called CheckDoc which make all possible combinations for UTF8/UTF16LE/UTF16BE/ANSI with line enconding CRLF, LF, CR with BOM/No BOM (ANSI always without BOM). Also this show the algorithm works. And also show how we can program to save various combinations (reading is automatic, unless we suggest the type, although that isn't always a command because for some types algorithm are sure about it).
    You can open any text file with the inner editor of M2000 console (press Esc to save it or Shift F12 to not save it):
    Edit "TestDocUTF8.txt"
    You can open this file using the defaul application for txt files:
    Win "TestDocUTF8.txt"
    or
    Win TestDocUTF8.txt
    Some statements may get filenames/paths without quotes, but not Edit because without "" make/edit modules

  2. fix a problem with a comment using ' after calling a sub...in another sub only;

Module TestModule {
	alfa(10)' no problem here
	End	
	sub alfa(m)
		beta(m*2)'here was the problem
		Print m
	End Sub
	Sub beta(x)
		Print x, "inner"
	End Sub
}
TestModule

Version 14 Revision 36
Fix Eval(), now Works for Standard types like numeric types. So in this example Eval() return number in any case. So found the pointer to group execute the Value part of Class alfa.

class alfa {
	{Read z as double=10}
	x=z
	id=int(rnd*100)
	value {
		=.X*100
	}
	remove {
		? "deleted "+.id
	}
	' if we comment these lines
	' then we get a uinque pointer
	' so array(b) return a copy of actual object
	{ ' return a pointer (object may have multiple pointers)
		' standard group has a unique pointer.
		->group(alfa)
		break
	}
}
// numeric, pointer to group, numeric, pointer to group, numeric
a=(1,alfa(5),3,alfa(15),5)
link a to a()
b=each(a)
variant z
while b	
	' fixed eval to work with nornal numeric values too
	' we need eval() to run value part of class alfa
		print eval(array(b)), b^   ' return a copy - but we have copy on pointer
		print eval(a(b^)), b^  ' a() always return the item
end while
clear a
print len(a)=0

Version 14 Revision 35

  1. fix a type problem in read for basic like programs (when we use BASIC statement)
  2. NEW: ON X RESTORE 100, 200, ALFA, 500, BETA
    When we use BASIC the RESTORE move the hidden pointer to choose the next DATA statement (DATA inside blocks { } skipped)
    So now there are 3 variations for ON (ON x GOTO....|ON x GOSUB....|ON x RESTORE....)
  • also help file updated.

Version 14 Revision 34
Advanced handling of buffer arrays. Now we can use object arrays to hold buffer arrays and address individual fields of buffer.

  1. Example Simple
structure simple {
	x as double
	y as double
	{ StrPtr as long} ' we make a union (4 bytes as long and string)
	name1 as string
}
simple one[5], zero
zero|name1="This is a BSTR string"
Print len(Simple)=20 ' 20 bytes, 2x8 bytes double, 4 bytes pointer to string
one[3]=zero ' copy to one at index 3 (4th item)
Print len(zero)=20, len(one)=20*5  ' 20 bytes and 100bytes
print Len(one[3]|name1)=21 ' characters = 21 words = 21*2 bytes
print one[3]|StrPtr  ' this is the address of the string
print one[0]|StrPtr=0  ' this is null string
print Len(one[0]|name1)=0
' now start the real example
Object alfa[3], beta[3][2]  ' max two index holder - but as you see we can put anything inside
alfa[1]=one
print alfa[1][3]|name1="This is a BSTR string"
print alfa[1] is one, " : True"  ' we have the same object
alfa[2]=buffer(one)  ' we get a copy of all items
alfa[3]=one[3] ' using one[3] we get a copy of item 3
print alfa[2] is one, " : False"  ' we have different objects
print alfa[2][3]|name1
print alfa[1][3]|StrPtr=one[3]|StrPtr, " : True"
print alfa[2][3]|StrPtr=one[3]|StrPtr, " : False"
print len(alfa[3])=20  ' one only item
print alfa[3]|name1="This is a BSTR string"
print alfa[3]|StrPtr=one[3]|StrPtr, " : False"
beta[3][0]=one
print beta[3][0] is alfa[1], " : True"
beta[3][0][3]|name1="New string"
print alfa[1][3]|name1="New string", " : True"
print one[3]|name1="New string", " : True"
' we can put an object in an array of objects too
beta[3][2]=alfa
print beta[3][2][1][3]|name1="New string", " : True"
zero=beta[3][2][1][3]  'we get the index 3 of object at beta[3][2][1]
' zero is a copy 
print zero|name1="New string", " : True"
print zero|StrPtr<>beta[3][2][1][3]|StrPtr, " : True"
zero=beta[3][2][1]
zero[3]|name1="last string"
' zero now point to beta[3][2][1]
print zero is one, " : True"
print zero is alfa[1], " : True"
print zero is beta[3][2][1], " : True"
print zero is beta[3][0], " : True"
print beta[3][0][3]|name1="last string", " : True"

  1. Example Hard
structure simple {
	x as double
	y as double
	{StrPtr as long} ' we make a union
	name1 as string
}
structure bigone {
	{simple};   ' import simple (using ; we bypass the union mechanism)
	z as double * 100
}
structure bigtwo {
	s as simple * 4
	z as double * 10
}
bigtwo two[10]
bigone one[5]
simple zero
zero|name1="This is a BSTR string"
print len(Simple)=20 ' 20 bytes, 2x8 bytes double, 4 bytes pointer to string
one[3]=zero 
print len(zero)=20, len(on...
Read more

Version 14 Revision 32

09 May 00:46

Choose a tag to compare

SHA256 2f34a0ae6d7377c1d66b5622dc354c45d07b5206ed6c0a98ed5954af2173be41

  1. Fix for Greek functions of type Function/end function for names with accents (normal functions registered in uppercase so any name first convert to uppercase with no accents for Greek names, but simple functions use the name as is with accents, we can call with uppercase name but we have to use the accents as those used on the definition of the function)

  2. I give more speed with removing a upper case conversion which not need any more.

Version 14 Revision 31

TEST CODE
this extends the error member for a enum type, when we place something not exist on the enum, in a variable type of that enum.
The extension work for parameters for modules/functions/subs, for the Let statement, for the Read statement.

CONST RECOVER_ERROR=RANDOM(-1,0)
GLOBAL BAD_NUMBER=-999
IF RECOVER_ERROR THEN
	PRINT "RECOVER_ERROR = TRUE"
	GLOBAL ENUM FLAGS_B {
	    Hold, Right, Left
	ERROR:
		    ERB=BAD_NUMBER
	}
ELSE
	PRINT "RECOVER_ERROR = FALSE"
	GLOBAL ENUM FLAGS_B {Hold, Right, Left}
END IF
GLOBAL ENUM FLAGS_A {
    In=-2, Out, FLAGS_B, Up, Down, Back, Front
ERROR:
    ERA=BAD_NUMBER
}
MODULE ALFA (M AS FLAGS_B) {
    IF M=BAD_NUMBER THEN PRINT "NOT GOOD VALUE":EXIT
    PRINT "OK - I DO THE JOB"
    PRINT "INDEX:";M^
    PRINT "VALUE:";M
    PRINT "NAME:";EVAL$(M)
    PRINT "TYPE:";TYPE$(M)
}
VAR Z AS FLAGS_A=Front
TRY OK {
	ALFA Z
}
IF ERROR OR NOT OK THEN PRINT "ERROR"+ERROR$
Z=Left
PRINT "INDEX:";Z^
PRINT "VALUE:";Z
PRINT "NAME:";EVAL$(Z)
PRINT "TYPE:";TYPE$(Z)
ALFA Z ' this pass ok

Version 14 Recision 30

  1. Now simple functions (made using function/end function) not need the @ before the name.
  2. Fix a problem which came with the new evaluator. The problem was inside parenthesis and the unary minus.
    b=-1 : ?(-b+abs(b)) ' 2 - the fault return 0
  3. Fix some problems not realy known.
  4. Now we can write BSTR type of string in structures/Buffers.
    The real string is written in a special hash table, and at the field we place the address of the first character or 0 (for empty)
Structure Alfa {
	a as double
	b as double
	Caption as string ' this is a BSTR string
}
Structure Beta {
	First as Alfa
	Second As Alfa*10
}
Beta Fields[20]
Fields[0]|First|Caption="This is a string - which take only 4 bytes in structure"
Fields[0]|First|a=1.23456e5
Fields[0]|First|b=0.45455
Print Fields[0]|First|Caption
PrintData(Fields[0]|First[]) ' pass a copy 
Fields[10]|Second[4]=Fields[0]|First[]
PrintData(Fields[10]|Second[4])  ' pass a copy 
Fields[10]|Second[4]=ChangeCaption(Fields[10]|Second[4], "New value for caption")
PrintData(Fields[10]|Second[4])  ' pass a copy 
Fields[10]|Second[4]|Caption="ok"
PrintData(Fields[10]|Second[4])  ' pass a copy 
Alfa JustAlfa
JustAlfa=Fields[10]|Second[4]
PrintData(JustAlfa)  ' pass a copy of a pointer
Print JustAlfa|Caption="ok..."  ' changed
PrintData(JustAlfa)  ' caption changed
JustAlfa|Caption="Final"
PrintData(JustAlfa[0]) ' pass a copy of buffer
Print JustAlfa|Caption="Final"  ' not changed
Print JustAlfa(0) ' absolute address of memory buffer

End
Sub PrintData(d as Alfa) ' pass by pointer
	Print "a:", d|a
	Print "b:", d|b
	Print "caption:",d|Caption
	d|Caption="ok..."	
End Sub
Sub ChangeCaptionByreference(&d as alfa)

End Sub
Function ChangeCaption(d as Alfa, newValue as string)
	d|Caption=newValue
	=d
End Function

Version 14 Recision 29

Update the capability to use the structure name as statement to make variables and arrays. Now we can append new members and we can process the old version of the same name type.

test program:

structure alfa {
	x as long
	y as long
}
buffer kappa as alfa*10
old_alfa=alfa  ' now old_alfa is also a statement for new variables
Structure alfa append {
	z as long
}
buffer delta as alfa*10

? old_alfa is alfa = false ' true, old_alfa hold previous alfa
d=kappa[2]
z=delta[3]
? len(d)=8, len(z)=12

? type$(d)="Buffer", type$(z)="Buffer"
list errors clear
// ? valid(z|z)=true, valid(d|z)=false
// we get the error on the list (from second valid() function)
/ errors just written to list but skipped through valid()
List errors

buffer d as alfa*100  ' now works  ' previous alfa
buffer z as alfa*100  ' now works
if rnd>0.5 then
	buffer dd as old_alfa*10   ' dd is [alfa:10] the previous alfa
else
	' using upgrade 
	old_alfa zz[10]	' now this works too and make olf Alfa
end if
? len(d)=800, len(z)=1200
d1=buffer(d) ' get a copy of d
? d is d1 = false ' true
function ab(d2 as old_alfa){ ' new now take the type from actuall pointer
	=d2
}
d2=ab(d1)
? d2 is d1  ' true we get the pointer to d1
? "ok", len(d1), len(d2)
list ' this is for listing variables.
Modules ?

Version 14 Revision 28

This is one of the last revisions for version 14. I drop one UDT, and maybe I work later to eliminate all Public UDT . I want the M2000.dll to be reg free. The last version/revision Reg Free was version 12 revision 8.

So this version has nothing new from the M2000. Nothing to fix. But has a manifest, so get the dll and find if the manifest works.

There is a bat file which have the command and parameters to make the manifest (using then mt.exe from Microsoft).

Also the mexe.vbp which made the M2000.exe now has the vbp file (the newer one, I have go to version 2.8 and the old one show 2.5, sorry)

Version 14 Revision 27

08 May 03:21

Choose a tag to compare

sha 256 bf81b03dd4d418faf140c045ba8cc29b7ffaef27d42286d27e6f6e8a86492db2

This revision was initial the first of Version 15 but I change my mind so this is it. The last revision has the best Select case.
Before this revision Select Case has many resrrictions. All of these are now gone.

Locale 1033
Flush
Prototype {
Module FindE {
	Function comp_e (n, decimals ){
		unit=n:n/=decimals:For i=decimals-1 to 1:n=Unit+n/i:Next i:=n
	}
	p=4000
	k=comp_e(biginteger("1"+string$("0", p)), p)
	string t1=str$(k), t=left$(t1, 39)
	if len(t1)>39 then
		for i=40 to len(t1) step 40
			t+={
			}+mid$(t1, i, 40)
		next
	end if
	all=(comp_e(1@, 28))+" Decimal"+{
	}+(comp_e(1, 19))+" Double"+{
	}+(comp_e(1~, 11))+" Float"+{
	}+(comp_e(1#, 8))+" Currency"+{
	}+ left$(t,1)+locale$(14)+mid$(t,2) +" Arbitrary-precision :"+p
	Clipboard all
	Report all
}
FindE
} as this$
	
Report this$
L=len(this$)
Enum NewLine {
	NL_Cr=chr$(13)
	NL_lf=chr$(10)
Error:
	NL_no=""
}
Enum WhiteSpaceBasic {
	W_Space=" "
	NewLine
	W_tab=chr$(9)
	w_nbsp=chr$(160)
}
Enum WhiteSpace {
	WhiteSpaceBasic
error:
	W_no_WhiteSpace=""
}
Enum WordSubTerminator {
	WST_Open_parenthesis="("
	WST_Open_bracket="["
	WST_dot="."
	WST_bar="|"
error:
	WST_no_WordSubTerminator=""
}
Enum ExprOperatorBasic {
	EO_Equal="="
	EO_Add="+"
	EO_Sub="-"
	EO_Mul="*"
	EO_Div="/"
	EO_Low="<"
	EO_Gre=">"
	EO_Exp="^"   ' also M2000 has ** too
	EO_Exclamation ="!"
}
Enum ExprOperator {
	ExprOperatorBasic
error:
	EO_no_ExprOperator=""
}
Enum WordTerminator {
	WhiteSpaceBasic
	ExprOperatorBasic
	WT_OpenBracket="["
	WT_CloseBracket="]"
	WT_OpenParenthesis="("
	WT_CloseParenthesis=")"
	WT_OpenBlock="{"
	WT_CloseBlock="}"
	WT_Colon=":"
	WT_SemiColon=";"
	WT_Coma=","
error:
	WT_no_WordTerminator=""
}
Enum ExprPar {
	EP_OpenParenthesis="("
error:
	EP_no_ExprPar=""
}
Enum Digit {
	D_zero="0"
	D_one="1"
	D_two="2"
	D_three="3"
	D_four="4"
	D_five="5"
	D_six="6"
	D_seven="7"
	D_eight="8"
	D_nine="9"
}
Enum UnaryOperatorSymbol {
	UO_plus="+"
	UO_minus="-"
error:
	UO_no=""
}
Enum IntegerFirstDigit {
	UnaryOperatorSymbol
	Digit
error:
	UO_no_IntegerFirstDigit=""
}
Enum DigitDot {
	Digit
	DD_dot="."
error:
	DD_no_dot=""
}
Enum LastDigits {
	Digit
	LD_e1="E"
	LD_e2="e"
error:
	LD_no_digit=""	
}
Enum OnlyDigits {
	Digit
error:
	OD_no_digit=""
}
White=W_Space
Enum StringOpen {
	SO_44=""""
	SO_123="{"
error:
	SO_no=""
}
Enum StringClose {
	SC_44=""""
	SC_125="}"
error:
	SC_no=""
}
Enum StatusValue {
	White_Space
	DigitEntry
	First_Dot
	ParameterBlock
	String_type1
	String_type2
	Rvalue
	Remark
}
Enum Identifier {
	Statement
	StatementUseBlock
	StatementMayUseBlock
}
TypeOfIdentifier=Statement
Status=White_Space
i=0
boolean MayIHaveParameters, noFirst
word$=""
num$=""
string StrBuffer
long stracc, paracc
boolean onetime_dot=true, noFirst
q=List
lit=List
variant z, use4digits
z=W_Space
SkipName=0
Document MultilineString$
long op
zz=IntegerFirstDigit
LineNo=1
PosNo=i
while i<L
	i++
	k$=mid$(this$, i, 1)
	select enum Status
	case Remark
		z=@Pack(k$, NewLine)
		if z<>"" then
			Status=White_Space
			i++
			PosNo=i
			continue
		end if
	case ParameterBlock, Rvalue
		z=@Pack(k$, NewLine)
		if z<>"" then
			Status=White_Space
			'i++
			PosNo=i+1
			LineNo++
//				? LineNo, i-PosNo+2
			continue
		end if
		zz=""  ' reset - becareful zz must not be of  type of variant
		if k$="/" then if mid$(this$,i,2)="//" then Status=Remark:i++:continue
		if k$="\" then Status=Remark:continue
		if k$="'" then Status=Remark:continue
		if num$="" and word$="" then zz=@Pack(k$, IntegerFirstDigit)
		if zz="" then
			z=@Pack(k$, WordTerminator)
			if Status=Rvalue then
				if z=WT_OpenBlock then
					if TypeOfIdentifier=StatementMayUseBlock else
						z=""
					end if
				end if
			end if
		else
			z=@pack(k$, UnaryOperatorSymbol)
			if z="" then
				onetime_dot=true
				op=i-PosNo
				num$=k$
				backstatus=Status
				use4digits=DigitDot
				Status=DigitEntry
			else
				z=@pack(mid$(this$, i+1,1), DigitDot)
				if z<>"" then
					z=""
					onetime_dot=true
					op=i-PosNo
					num$=k$
					backstatus=Status
					use4digits=DigitDot
					Status=DigitEntry
				else
					z=zz
				end if
			end if
		end if
		if z<>"" then
			if word$<>"" then
				word$=ucase$(word$)
				If not exist(q, word$) then  Append q, word$
				Print word$, " at "+LineNo+", "+op
				word$=""
			else.if num$<>"" then
				If not exist(lit, num$) then  Append lit, num$
				Print num$, " at "+LineNo+", "+op
				num$=""
			end if
			if z=WT_OpenParenthesis then
				paracc++
			else.if z=WT_CloseParenthesis then
				if paracc<1 then Ststus=White_Space else paracc--
			else.if z=WT_OpenBlock then
				SkipName=0
				TypeOfIdentifier=Statement
			end if
		else.if Status=DigitEntry then	
		else.if word$="" then
			z=@Pack(k$, StringOpen)
			if z="" then
				op=i-PosNo
				word$=k$
			else
				if z=SO_44 then
					Status=String_type1
					op=i-PosNo
					StrBuffer=""
				else
					Status=String_type2
					clear MultilineString$
					op=i-PosNo
					stracc=0
				end if
			end if
		else
			word$+=k$
		end if
	case White_Space
		if k$="/" then if mid$(this$,i,2)="//" then Status=Remark:i++:continue
		if k$="\" then Status=Remark:continue
		if k$="'" then Status=Remark:continue
		z=@Pack(k$, WordTerminator)
		if TypeOfIdentifier=Statement then
			if z=SO_123 then
				z=""
			else.if z=EO_Equal then
				Status=Rvalue
				backstatus=White_Space
			else.if z=EO_Low then
				if mid$(this$, i+1, 1)=EO_Equal then
				 i++
				 Status=Rvalue
				 backstatus=White_Space
				 end if
			else.if z=NL_Cr then
				Status=White_Space
				PosNo=i+1
				LineNo++
//					? LineNo, i-PosNo+2
			end if
		end if
		if z<>"" then
			if word$<>"" then
				word$=ucase$(word$)
				If not exist(q, word$) then  Append q, word$
				Print word$, " at "+LineNo+", "+op
				if skipname>0 then
					 skipname--
				else
					if TypeOfIdentifier>Statement then
						MayIHaveParameters=false
					end if
					select case ucase$(word$)
					case "MODULE"
						SkipName=2
						MayIHaveParameters=true
						TypeOfIdentifier=StatementUseBlock
					case "FUNCTION"
						SkipName=2
						MayIHaveParameters=true
						// function/end function not use BLOCK
						TypeOfIdentifier=StatementMayUseBlock				
					case "SUB"
						SkipName=1
						MayIHaveParameters=true
						TypeOfIdentifier=Statement
					case "WHILE", "FOR", "PEN"
						Status=Rvalue
						TypeOfIdentifier=StatementMayUseBlock
					case "ENUM","ENUMERATOR", "LAYER", "WIDTH", "COLOR", "TASK.MAIN"
						SkipName=1
						TypeOfIdentifier=StatementUseBlock
					case "END", "NEXT"
						SkipName=1						
					case else
						TypeOfIdentifier=Statement
						Status = Rvalue
					end select
				end if				
				word$=""
			else.if num$<>"" then
				If not exist(lit, num$) then  Append lit, num$
				Print num$, " at "+LineNo+", "+op
				num$=""
			end if
			if z=NL_Cr then
				if TypeOfIdentifier=StatementUseBlock then
					Pen 15 {Print "Warning not block found { }"}
				end if
				TypeOfIdentifier=Statement
				i++
				continue
			end if
			if z=WT_OpenParenthesis and TypeOfIdentifier>Statement then
				Status=ParameterBlock
				SkipName=0
				paracc=0
			else.if z=WT_OpenBlock then
				SkipName=0
				TypeOfIdentifier=Statement
			end if
		else.if word$="" then
			if z="" then
				z=@Pack(k$, StringOpen)
				if z="" then
					op=i- PosNo
					word$=k$
				else
					if z=SO_44 then
						Status=String_type1						
						op=i-PosNo
						StrBuffer=""
					else
						Status=String_type2
						clear MultilineString$
						op=i-PosNo
						stracc=0
					end if
				end if
			end if
		else
			word$+=k$
		end if			
	case DigitEntry
//			? k$, type$(use4digits)
		z=@Pack(k$, use4digits)
		if  noFirst then use4digits=OnlyDigits
		if (z="." and not onetime_dot) or z="" then
			If not exist(lit, num$) then  Append lit, num$
			Print num$, " at "+LineNo+", "+op
			num$=""
			Status=BackStatus
			noFirst=false
			i--
		else.if z=LD_e1 or z=LD_e2 then
			use4digits=IntegerFirstDigit
			num$+=k$
			onetime_dot=false
		else
			num$+=k$
			if k$="." then onetime_dot=false: use4digits=LastDigits
		end if
	case String_type1
		if @Pack(k$, StringClose)=SC_44 then
			k$=Quote$(strBuffer)
			if not exist(lit, k$) then Append lit, k$
			Print @form$(k$), " at "+LineNo+", "+op
			Status=Rvalue
		else
			z=@Pack(k$, NewLine)
			if z="" then strBuffer+=k$ else 1000
		end if
	case String_type2
		if @Pack(k$, StringClose)=SC_125 and stracc=0 then
			 if doc.par(MultilineString$) > 1 then
			 	clipboard MultilineString$
				strBuffer=paragraph$(MultilineString$, 2)
				for j=1 to len(strBuffer)
					z=@pack(mid$(strBuffer,j,1), WhiteSpace)
					if z="" then exit
				next
				if z="" then
					for k=2 to Doc.Par(MultilineString$)
						strBuffer=paragraph$(MultilineString$, k, -1)
					 	Insert to k MultilineString$=Mid$(strBuffer, j)+{
					 	}
					next
				end if
			end if
			Pen 15 {Print #-2,"{"+MultilineString$+"}"}

			k$="{"+String$(MultilineString$)
			Print @form$(k$, 9)+"}", " at "+(LineNo-doc.par(MultilineString$)+1)+", "+op
			k$+="}"
			if not exist(lit, k$) then Append lit, k$ // pack string with escape codes/
			Status=Rvalue
		else
			if k$=SO_123 then stracc++ else.if  k$=SC_125 then stracc--
			if k$=chr$(13) then k$=chr$(13)+chr$(10): lineNo++: PosNo=i-1
			if k$=chr$(10) else
				MultilineString$=k$
			end if
		end if
	case else
		exit
	end select
end while
? Eval$(Status), Eval$(TypeOfIdentifier)
? "L=";L,"I=";i
gosub KeyPress
k=each(q)
Print "Identifiers:";len(q)
while k
pen 10 {print str$(k^+1, "0000 ")+ eval$(k)...
Read more

Version 14 Revision 26 (final)

30 Apr 21:21

Choose a tag to compare

SHA 256: 18254ae2ac8a7b1515f8808ba4df24d8a877c40f614598ba086a556951d19730

This is the last revision for Version 14. I have to upgrade the M2000paper.pdf the English Manual, for the basics. There is a Help system in Interpreter. You can write Help All to get the list of all topics.

See readme.txt

Version 14 Revision 22-2

26 Apr 22:23

Choose a tag to compare

I put the right glis4 control and a new setup file as Revision 22-2 (for the setup, the revision of version 14 is 22)
Form 21 & 22 I do a copy and I forgot to define as default the text property of glis4 user control.

Revision 22

  1. I do a check with all examples from previous releases, and this revision passed. I made a lot of fixes (due to the change of the parser). So the last error was on Return statement. This statement may have a String Expression or a Numeric or none (This statement has 3 different things, using a container type object we can return values in a series of indexed members, using a string is the database which we return changed values, without parameter is the Return from GOSUB).
  2. Many improvements. Now Editor is ok and we can click in a name with a dot before and if continue click on it we get different parts, so one of them is what we want, to use the F2/F3 search buttons.
  3. Look the module FindWord in Info. Now search all modules not for one word but a list of words if we like that. we can use | as separator or we can define our.

FindWord "Buffer|[]"
FindWord "Print, Dim, For", ", "

Revision 21

  1. Fix a mistake from revision 20 which break the ctrl Z/ctrl Y for all editors (console editor and EditBox editor). Now is ok.
  2. Fix the missing repair for Fill @ statement variant, for using a string or number properly. This affects KB module (now notes shown as expected).

Revision 20

This revision has many additions.
The best:

Faster about 17% (less time to run) - this is a speedup of 20% (1/0.83=1.20451). Because the change its huge, maybe some code will break although I do a test through the modules in Info file (this is the reference module's). Before I finish that search I found a lot of faults and I fix them. Maybe something I miss it. So be careful.

I found a way to call another m2000.exe from the one which run and open as child window. Check: Clock. The clock run on own M2000.exe but with a magic way became a child window, which means always stand in front of the caller. Because we can open any number of windows on the first m2000.exe (try Form44 module) we will see the clock to be like those child windows, so one can overlap the clock, but never the clock go behind the console (main form) of M2000.exe which call it. Another example is from Compiler module. We can compile any of the examples and choose to use the transpiler (not virtual machine but M2000 code), then a new messagebox ask if we want to run in our console or as child window (in a new m2000.exe). If we decide the last option, we get a "scrabbled" gsb file (which hide the code) and immediately run.

Some additions to Editor ctrl 1 change marked text to Upper Case. Ctrl 2 change marked text to Lower Case. Without marked text we change to upper or lower case without using the "toggle" Caps Lock (you don't have to look for the status, these are force changers). Ctrl 4 or Ctrl / used for comment/uncomment a line or more.

Version 14 Revision 18

25 Mar 07:38

Choose a tag to compare

MD5 b1fd8086b888a056f422e38ef7f04e88 for M2000language.exe

See readme.txt

Versiion 14 Revision 17-18

See Readme.txt

  • Advanced midi control, using dotted notes, ties, tuplets, staccato/legato. (I use AI, ChatGpt to understand those terms, and to test my interpreter to be as expected). This is the second time for using AI for M2000, but this time AI understand and write M2000 programms for testing midi channels. Very cool. You can find JOY module which have the song Ode to Joy (music written by AI for M2000, using the M2000 language for music).

  • Write statement can be broke to more than one line for the same line output (we place comma as last character so we add anonter Write).

Versiion 14 Revision 16

Time zones now loaded from registry.

Versiion 14 Revision 15

A lot of work - see the Readme.txt

Version 14 Revision 14

  1. BUG removed: In Trace code with Test form, you place the STOP statement in the Bottom textbox, and the execution move to console like cli, but in the running code, and you close the Test Form, at the exit the form not exist and by a mistake the system return to trace without the form, and this return the error "Object variable or With Block variable not set" which is an error from VB6. This error not hang the M2000 Interpreter. Fixed.
  2. BUG removed: In print if we have some wrong encoding text (from binary data) happen sometime to find a wrong character which cannot pring (no data to handle the print) and stop advance to next character. Fixed
  3. Using
    str$(wide_string_encoding) return narrow_string_encoding based on locale
    and
    chr$(narrow_string_encoding) return wide_string_encoding based on locale

sometime think that these can be used for binary date, to get the ASCII equivalent, and letter to cut the string as a part and then return that part to binary data from wide to narrow bytes. But this isn't true. The chr$() get the binary data, for example 10 bytes and produce 20 bytes with 10 characters mapping the locale. So for some numbers the mapping return the same number. The problem is with the other numbers which turn to something else. If we make the data using the STR$() with same locale we have no problem. although the actual converted to wide data would be not the same with the pure data which have the same number as wide (2 bytes) and as narrow (1 byte) encoding.
So I write two encoders, one WIDE2BYTES and another BYTES2WIDE for using with STRING$() function which have many decoders/encoders.

This is an example of using BYTES2WIDE in STRING$() instead of CHR$() an prove why we get wrong data using the later:

buffer b as byte*256
for i=0 to 255:b[i]=i:next
locale 1032
z=chr$(eval$(b))
faults=0
for i=0 to 255
	if b[i]<>chrcode(mid$(z,i+1,1)) then
	 	// Print "Error "+i, b[i], chrcode(mid$(z,i+1,1)), mid$(z,i+1,1)
	 	faults++
	 end if
next i
Print "faults = ";faults  // 93 for locale 1032

locale 1033
z=chr$(eval$(b))
faults=0
for i=0 to 255
	if b[i]<>chrcode(mid$(z,i+1,1)) then
	 	// Print "Error "+i, b[i], chrcode(mid$(z,i+1,1)), mid$(z,i+1,1)
	 	faults++
	 end if
next i
Print "faults = ";faults  // 27 for locale 1033

z=String$(eval$(b) as BYTES2WIDE)   // and reverse WIDE2BYTES
faults=0
for i=0 to 255
	if b[i]<>chrcode(mid$(z,i+1,1)) then
	 	faults++
	 end if
next i
Print "faults = ";faults   /// 0 faults
GoodWideData=Z
// This is the real problem:
// This return True, because each function of str$() and chr$() use the same locale.
Print Eval$(b)=str$(chr$(Eval$(b)))
// But the intermediate result, the WideData are not the same as the GoodWideData:
Print GoodWideData = chr$(Eval$(b))   ' false
// so if we get binary data and want to expand them to Wide char for farther processing
// we have to use the new decoder/encoder of String$() statement

Version 14 Release 13

One fault. An empty type was converted to string as "0" not as "" (empty string). We may get empty type from COM objects.

Version 14 Revision 12

  1. Now we can make PNG file in a buffer ->
    if B is another image in a buffer or is a string with dib data. If the image B is a metafile then then PNG has transparecy 100% on those pixels which not used by the metafile.
    A=IMAGE(B as PNG)
  2. fix an error in PSET for metafiles.
  3. minor details

Version 14 Revision 11

  1. FORMALABEL variant using ! for non antialiasing text rendering. See help FormLabel
  2. IMAGE() now works for a bitmap in a string using the same as for PNG except the transparent color. See help Image()
    also fixed on the resize to not leave a line in right and potom edge.
    3)Report now has another clause: SCROLL for the specific variants who use selected lines to display. So without Scroll we get the lines only which we see without scroll (same in a loop). Using Scroll we get the same like the Report without limit lines (the standard Report). So the SCROLL enable the scroll hold system for page view.
    4)fixed in OpenGl the problem with background not alignment as excpected (removed a multiplication 1.01 which alter the size of the texture)

Version 14 Revision 10
1)BigInteger issues:
1.1 str$(2u,"") now return 2 (before an empty string).
1.2 str$(1212313u, "#,###") not supporeted so we get the number (no error raised).
1.3 Problem on expression evaluator:

' problem for <10 revision. Now the two parts are equal.
var a=1000234, b=34450
?  (a+1)*b
biginteger z=a, zz=b, one=1
? z, one
?  (z+one)'*zz
?  (one+z)'*zz
? zz* (z+one)'*zz
?  zz*(one+z)'*zz
? (z+one)*zz, "???"
? (one+z)*zz
? (z-one)*zz, "???"
? (one-z)*zz, "good"
? (-z*one-one)*zz, "???-"
? (-one*z-one)*zz
? (z*one-one)*zz, "???+"
? (one*z-one)*zz
?  z*zz+one*zz
?  one*zz+z*zz
clear
var a=1000234, b=34450
? "----------long long no problem----------------"
?  (a+1)*b
long long z=a, zz=b, one=1
? z, one
?  (z+one)'*zz
?  (one+z)'*zz
? zz* (z+one)'*zz
?  zz*(one+z)'*zz
? (z+one)*zz, "???"
? (one+z)*zz
? (z-one)*zz, "???"
? (one-z)*zz, "good"
? (-z*one-one)*zz, "???-"
? (-one*z-one)*zz
? (z*one-one)*zz, "???+"
? (one*z-one)*zz
?  z*zz+one*zz
?  one*zz+z*zz

  1. Advanced OpenGl support - now can load images/textures2d more than background.

  2. Report statement has a hold function waiting user input a key or a mouse click when print 3/4 of output lines (except on printer and when run in a thread or an event service function). So now if the output is not visible then no hold happen. Also this works for Users Forms when the form wait for user input (only mouse) we can move the window without the holding function restart printing. Also if we minimize the form then automatic restrart printing.

// Example on form:
document a$
for i=1 to 1000
a$=str$(i,"0000")+" "+string$(chrcode$(random(65, 90)), random(10, 30))+{
}
next
a$=string$(chrcode$(random(65, 90)), random(10, 30))
declare form1 form
declare image1 Image Form Form1
with form1, "visible" as visible, "titleheight" as th, "width" as w, "height" as h
method image1, "move", 0, th, w,  h-th
once=false
function image1.click {
	if once then exit
	once=true
	layer image1 {
		report a$
		cls
	}
	after 200 {
		try {once=false}
	}
}
method form1, "show", 1
wait 500
threads erase
declare Form1 Nothing

Example printing on M2000 console's background (we hide foreground). Try to minimize the console, (you have to do this from the context menu from the taskbar, on Windows 10 and 11 you have to press Esc when the a popup menu first pop, and then you get a small window where on the title bar you do a right mouse click to open the context menu).

document a$
for i=1 to 1000
a$=str$(i,"0000")+" "+string$(chrcode$(random(65, 90)), random(10, 30))+{
}
next
a$=string$(chrcode$(random(65, 90)), random(10, 30))
HIDE
k=10
BACK {
	report A$
	cls
	k-- : if k=0 then exit
	if not keypress(32) then loop
}
SHOW

Example printing on M2000 console. Try to minimize the console (you have to do this from the context menu from the taskbar).

document a$
for i=1 to 1000
a$=str$(i,"0000")+" "+string$(chrcode$(random(65, 90)), random(10, 30))+{
}
next
a$=string$(chrcode$(random(65, 90)), random(10, 30))
k=10
' just remove HIDE/SHOW and BACK from the previus example
{
	report A$
	cls
	k-- : if k=0 then exit
	if not keypress(32) then loop
}

Also we can use one of 32 layers above console's layer:

document a$
for i=1 to 1000
a$=str$(i,"0000")+" "+string$(chrcode$(random(65, 90)), random(10, 30))+{
}
next
a$=string$(chrcode$(random(65, 90)), random(10, 30))
k=10
layer 1 {
	window 15, 10000,8000;
	show
}
Layer 1 {
	report A$
	cls
	k-- : if k=0 then exit
	if not keypress(32) then loop
}
Layer 1 {hide}

4)Fix the BASIC/DATA/RESTORE for Greek language (BASIC always in English, is the name of the language).

Version 14 Revision 9

DATA used for sending to current stack of values to last position items. When we execute BASIC statement in a module we change DATA tp work as in BASIC, also FOR NEXT work as BASICS'S and DIM A(10) make 11 items array from 0 to 10, but we can do this DIM A(0 to 9),

Also READ statement change so for reading from stack of values we use @READ (@ always used for skipping shadowing the reserved words - the same reason simple functions which made using Function End Function at the end of a module cannot have same name as those reserved for internal functions, they both use @ to call).

DATA works like in BASIC after the BASIC statement (per module/function) but we can use standard statement using @DaTa for those modules which we do that (events and threads not use this temporary switch by design). Also we can use RESTORE (new statement) to change the reading start for READ statement. So a RESTORE restore to first DATA in module, and RESTORE 100 or RESTORE alfa restore to first data from label 100 (or 0100 or 00100) or label alf...

Read more

Version 14 Revision 8

16 Mar 03:01

Choose a tag to compare

MD5 checksum:6ccabe8d4190bd724c21cb6e541902f8

Greek manual - Version 14 Revision 6 - With Greek Manual

  1. Fix IsNum and Number read only variables.
push 12312312u   ' we push to stack a BigInteger (is an object)
Print isnum  ' fixed - now return true
long long z

z=number*100 ' now number pop the BigInteger
list ' see the variables
2) Fixed the Binary block (which have BASE64 bytes). The problem was the tabs. So if we place the Binary block and move it by placing tabs at the same lines as the data old code raising error at converting to bytes. Now fixed, character 9 is white space now for this statement
So now this work (there are tabs before the code

	BINARY {
		kwOVA5kDkQMgAKcDkQOhA5ED
	}  AS A$
	PRINT A$
  1. The Matrix type of variable (exist on Math2 object), now has a library Matrix in info file. Math library now has upgraded Determinant function and a new function Inverse Matrix.

  2. Update/Insert new Modules on Info file. Matrix, Server1 (we make an Http Server), FFT (fast fourier transform), Simpson (Simpson Rule, a numerical integration technique), Teacher (A speech program for English Language).

Version 14 - Revision 7

22 Feb 20:39

Choose a tag to compare

MD5 checksum: f6bebbe3975ebd4c7cf6d50cd7bbeff6

Greek manual - Version 14 Revision 6 - With Greek Manual

The read only variable internet call a function which use the 142.250.187.100:80 to check internet connection. But for some reason this ip not repsonsed.
So I put two more. This fix also fix the read only variable internet$ which return the ip of the current pc from outside (which also check the same function for checking the internet connection).

We can write M2000 code for the old Internet read only variable:

// the CLIENT object is the cTlsClient object (cTlsClient1.cls)
FUNCTION check_internet {
	DECLARE CLIENT CLIENT
	WITH CLIENT, "NoError", TRUE
	METHOD CLIENT, "SetTimeouts", 100, 300, 200, 300
	// change 100 to 0 or 10
	METHOD CLIENT, "Connect","142.250.187.100", 80 AS CONNECT
	=CONNECT
}

We can write M2000 code for internet$

// HTTPS.REQUEST is object clsHttpsRequest (HttpsRequest.cls)
FUNCTION  get_ip$ {	
	DECLARE HttpsRequest HTTPS.REQUEST
	WITH HttpsRequest,"BodyFistLine" AS RESP$
	METHOD  HttpsRequest, "HttpsRequest", "HTTPS://ifconfig.co/ip" AS OK
	IF OK THEN =RESP$
}
PRINT get_ip$()

Version 14 Revision 6 - With Greek Manual

31 May 02:45

Choose a tag to compare

MD5 checksum: 02eeb765dee189d249f40513d679ed60

One bug on STACK statement when we pass a variable which hold a string with a stack as a string (for numbers/strings only). Name for variables now works with numbers inside name, so variable a1212$ can be used now.
This example now run as expected

ABC1$=STACK$(10, "HELLO", 5000)
STACK NEW {	
	STACK ABC1$, "NS"
	STACK
}
PRINT ABC1$

Version 14 Revision 5

  1. frac(expression!) return fraction of the result of expression. frac(expression) return fraction of the result of the rounded number ( at the 13th digit).
  2. Writable() now work without raising error for drives which didn't exist. Another way to check if a path may exist then ShortDir$(path$) return the short dir or if not exist return empty string. So shortdir$("a:")="" means drive a not exist.
  3. Declare a small fix for ..., which now we can use it in a multiline declaration, using optional remarks using ' or // or \:
mybuf$=String$(Chr$(0), 1000)
Declare Global MyPrint Lib C "msvcrt.swprintf" {
	&sBuf$,  ' byref pass - pass address of first byte of string
	sFmt$, ' by value pass
	... ' variadic parameters  - always as last parameter
	} 
A=MyPrint(&myBuf$, "P1=%s, P2=%d, P3=%.4f, P4=%s", "ABC", 123&, 1.23456, "xyz")
Print Left$(myBuf$,A)  ' A has the number of characters (words - 2 bytes per character)

Version 14 Revision 4

Fix statement FLOODFILL COLOR ... the variant of FLOODFILL which change the color at the point which we address the statement. This was broken from Version 14, rev 0 through 3.

Version 14 Revision 3

  1. Fix TEST function to display code for THREADS properly
  2. Some additional fixings

Version 14 Revision 2
Fix a tough to found error:
check this code, second time call of alfa raise "syntax error", for previous revision.

My Youtube Channel

module global  alfa {
	static beta=100
	read that
	? that, beta
	beta++
}
set alfa -1
set alfa -1

Version 14 Revision 1

  1. Comp module now work as expected (the a(index)=a, b, c if b and c was objects not assignment perform for that b and c. The a(index):=a, b, c was ok, now the a(index)=a, b, c works for objects too.
  2. Form X, Y statement works very nice (I found that sometimes a Linespac with -15 value happen; so I found what to do to correct it).
  3. For groups/classes we can include some statements inside a block inside the group/class body. Although we can use a constructor, this constuctor executed after the execution of the class body.
module InAClass {
	class alfa {
		{ //  x and a are local to function alfa()
		 // but not part of object
		 // we can take numbers from stack
			read ? x=10
			a=today+x
		}
		date lastdate=a
	}
	alfa a
	? a.lastdate
	alfa b(100)
	? b.lastdate, type$(b.lastdate)
	? val(b.lastdate-a.lastdate -> double)=90
	? a is type alfa, b is type alfa	
	list
	push a  ' we push the objct a to stack of values
}
InAClass
// we pop value from stack of values using Read
read export1
// class alfa erased but the object can be used
print export1.lastdate

module InAGroup {
	function alfa {
	 	read ? x=10   // we can put these two lines
		a=today+x     // in a block inside group alfa, before date definition
		Group alfa {
			type: alfa
			date lastdate=a
		}
		=alfa
	}
	' we can't use "alfa a" because function alfa isn't "class function"
	' also function alfa is local but class alfa is global until eraded (at exit from InAClass)
	a=alfa()  
	? a.lastdate
	b=alfa(100)
	? b.lastdate, type$(b.lastdate)
	? val(b.lastdate-a.lastdate -> double)=90
	? a is type alfa, b is type alfa	
	list
	push a
}
InAGroup ' same result as module InAClass
read export2
print export2.lastdate
  1. Private external functions:
class StartTime {
// check os before make functions
// but all declarations found function at the first call
// so because we have constructor (we need it to call the function QueryUnbiasedInterruptTime)
// this block can be erased
{
	declare info information
	with info, "IsWindows7OrGreater" as win7
	if not win7 then Error "Minimum os: Windows 7"
}
private:
	declare QueryUnbiasedInterruptTime lib "Kernel32.QueryUnbiasedInterruptTime" { long long &a} as integer
	timebase=1000000&&
public:
	lastvalue=0&&
	value {
		long long ret
		if .QueryUnbiasedInterruptTime(&ret) then
			.lastvalue<=ret/.timebase
		end if		
		=uint(.lastvalue)
	}
class:
	module StartTime {
		// so we can do the test at the constructor.
		declare info information
		with info, "IsWindows7OrGreater" as win7
		if not win7 then Error "Minimum os: Windows 7"
		long long tbase, ret, ret1
		decimal a
		profiler
		a = timecount+1000@
		if .QueryUnbiasedInterruptTime(&ret) then {
			while uint(timecount)<a {}
			if .QueryUnbiasedInterruptTime(&ret1) then {
				.timebase<= 10^int(log(uint(ret1)-uint(ret)))
			}
		}
	}
}
// the StartTime return value
StartTime=StartTime()
print StartTime;"sec"
print int(StartTime/60/60);"hours", now
print round(StartTime/60/60/24, 1);"Days"
// we can get a copy
Another=Group(StartTime)
Print Another;"sec"
// using a fake pointer - is a reference to StartTime as weak pointer
pointer2StartTime->StartTime
Print Eval(pointer2StartTime);"sec"
// now we get a true pointer to a copy of StartTime
pointer2StartTime->group(StartTime)
Print Eval(pointer2StartTime);"sec"
wait 1000
Print StartTime-pointer2StartTime=>lastvalue=1 ' true

Revision 0

  1. Improved printing using Quality factor on Raster type pages (we make the page like a layer and then send it for printing). We can rotate the page and put two pages in one page (see example Ver14) using emf type page (first we make a drawing and then send to printer). A pdf export using emf type send characters for characters, (and include fonts).. The bitmap type send bitmap so we can't copy text, by marking text. We can use 200dpi. 300dpi, 450 dpi and 600dpi for the bitmap page. M2000 handle the sizes under the hood.
  2. Interfaces and calling functions from interfaces. We can put the functions in a group (the default object of M2000).
  3. Buffers and Structures: Now we can use types for buffers if the Buffer is a type of a specific structure (as an array of that structure).