Like in Basic, in M2000 we can declare a variable by assigning a value to a name. We use $ as last char for strings always. We use % as last char for integers, but integers in M2000 are double with no decimals. A statement A%=5.5 assign value 6. All computations in M2000work on a double accumulator. Strings can store very large content (16bit, UTF16LE) and are BSTR (used in COM objects).
When we declare names using equal sumbol "=" as a name, the symbol "=" and an expression then a local name inserted at the Variable List. We can declate a variable in command line interpreter, or we say, using manual declaration: A=100 and now A is what we expected an A
Lets say that we make a module Alpha and in the code of Alpha we have A=100. Now a Alfa.A created. Every time, after local declaration, interpreter find local A and not A (from manual declaration). This is shadowing operation. A global variable has no hidden part, or module name, or function name, as part of the final name (lika Alpha.A for A in Alpha module).
If we wish to change value to global variable we have to use <=. When we use it, interpreter use name as is and search for it (using a hash function). If can't find then an error produced, because this "<=" is only for assigning a new value, not declaring a new variable.
The things get some peciuliar, if we think about groups of variables:
Group Example { X=10, Y=30}
Supposed that we make this group in Module Alpha. After declaration there are three variables: An Alpha.Example.X, an Alpha.Example.Y and Alpha.Example. The last variable is the object with a list of members. Each variable and member of Example group is local variable for Alpha.
See X and Y get initial values in Group declaration using "=". In Module Change, .X (dot ex) which is Group member need a dot and <= to change value. If we place a X=1000 then that X became a Change.X as a local X in Charge. When we wish to change Y outside Example we use a simple "=".
Group Example {
X=10, Y=30
Module Change {
.X<=1000
}
}
Example.Y=500
All of that are true, if this code is in a module or function, and that module or function is either in a group module or in simple module (or in a group function or in simple function). There is an exception, and this post has to clarify:
Groups passed by value or by reference. By referencc the member list used to define menbers and a new list for these members, and for each member's name there is a pointer to point to original value. So when we altert a "referenced" value, actually we altered the original value. This not hold for "referenced" member list. We expand list, expand the referenced group, without altering the original member list. By value we simple make a new group, with no name. When a Read statement, with a simple name, find in stack an anonymous group then make a new group using that simple name. Calling a module passing by value a group is the same as we Push a group in stack. Here we make a group from a class function, a constructor for a group (here using default constructor).
Class Alfa {
X=10
Y=5
}
Push Alfa()
Read Beta
List
With List command we can see the names of all variables. (with Module ? we can see the names of all modules/functions). Private members arn't displayed.
We can delcare Global Groups. And that is not "good" except we know why we do that. The reason for this ilustrated in the following example:
Class Alfa {
X=10
Y=5
}
Group Delta {
Module Look {
\\ Read Beta
Read New Beta
Beta2=Alfa()
Group Beta3 {
X=10
Y=5
}
List
}
}
Global Beta=Alfa()
Beta.X<=2000
Delta.Look Alfa()
Print Beta.X
If we use Read Beta in module Look in Delta, then because Beta is a global name, we get the a copy from group in stack, so X became 10. Using Read New we tell to Interpreter that Beta is a new name, so a new Beta (as Delta.Look.Beta) declared. Module's name is Delta.Look.
Beta.X and Beta2.X because are made by aunamed groups (class return such a group) have no other parts, so when we wish to assign a value we have to use <= like these examples: Beta.X<=400 and Beta2.X<=400. But Group Beta3 has Beta3.X as Delta.Look.Beta3.X so need a simple =, so a Beta3.X=400 is ok.
If we change variables with properties then the same hold: If we declare a group from an anonymous group, and the name of that group is the same with a global one, then we write on the global one, except we use READ NEW.
Class Alfa {
Property X=10
Property Y=5
Module TestMe {
\\ .[X] is a value
\\ .X is a group which we can read or write, or read and write
Print .[X], .[Y]
}
}
Group Delta {
Module Look {
\\ Read Beta
Read New Beta
Beta2=Alfa()
Group Beta3 {
Property X=10
Property Y=5
}
Beta.X<=500
List
Print Beta.X, Beta2.X, Beta3.X
Beta.TestMe
}
}
Global Beta=Alfa()
Beta.X<=2000
Delta.Look Alfa()
Print Beta.X
So now we can see a bigger example, using by reference too:
Module Global CheckRef {
Read &group1
Print group1.x, "!!!!!!!!!!!!!!"
}
Group A1 {
x=10
Property A$="ok"
}
Group Alfa {
Module Beta {
Read AA
AA.x++
\\ need (<=) because is in a function in a group and produced by Read
\\ all data members are like globals.
AA.x<=300
Print AA.x
Group BB {
X=10
}
\\ we can't use (<=) all members are like locals
BB.X=30
checkref &BB
checkref &AA
\\ List
}
Function Beta {
Read AA
AA.x++
\\ need (<=) because this group is in a function in a group and produced by Read
AA.x<=300
Print AA.x
Group BB {
X=10
}
\\ we can't use (<=) all members are like locals
BB.X=30
checkref &BB
checkref &AA
=BB
}
Function CheckFuncByRef {
Read &Func()
=Func(Group)
}
}
Alfa.Beta A1
Module Beta2 {
Read AA
AA.x++
\\ can't use (<=) because Beta2 Module isn't a group module
AA.x=300
Group BB {
X=10
}
\\ we can't use (<=) all members are like locals
BB.X=30
checkref &BB
checkref &AA
Print AA.x
\\ List
}
Function Beta2 {
Read AA
AA.x++
\\ can't use (<=) because Beta2() function isn't a group function
AA.x=300
Group BB {
X=10
}
\\ we can't use (<=) all members are like locals
BB.X=30
checkref &BB
Print AA.x
CheckRef &AA
=AA
}
Call Beta2 A1
A2=Alfa.Beta(A1)
A3=Beta2(A1)
Print "Check By Refrenece"
A4=Alfa.CheckFuncByRef(&Alfa.Beta(), A1)
Print A4.x, "_No problem"
A5=Alfa.CheckFuncByRef(&Beta2(), A1)
Print A5.x, "_No problem"
When we declare names using equal sumbol "=" as a name, the symbol "=" and an expression then a local name inserted at the Variable List. We can declate a variable in command line interpreter, or we say, using manual declaration: A=100 and now A is what we expected an A
Lets say that we make a module Alpha and in the code of Alpha we have A=100. Now a Alfa.A created. Every time, after local declaration, interpreter find local A and not A (from manual declaration). This is shadowing operation. A global variable has no hidden part, or module name, or function name, as part of the final name (lika Alpha.A for A in Alpha module).
If we wish to change value to global variable we have to use <=. When we use it, interpreter use name as is and search for it (using a hash function). If can't find then an error produced, because this "<=" is only for assigning a new value, not declaring a new variable.
The things get some peciuliar, if we think about groups of variables:
Group Example { X=10, Y=30}
Supposed that we make this group in Module Alpha. After declaration there are three variables: An Alpha.Example.X, an Alpha.Example.Y and Alpha.Example. The last variable is the object with a list of members. Each variable and member of Example group is local variable for Alpha.
See X and Y get initial values in Group declaration using "=". In Module Change, .X (dot ex) which is Group member need a dot and <= to change value. If we place a X=1000 then that X became a Change.X as a local X in Charge. When we wish to change Y outside Example we use a simple "=".
Group Example {
X=10, Y=30
Module Change {
.X<=1000
}
}
Example.Y=500
All of that are true, if this code is in a module or function, and that module or function is either in a group module or in simple module (or in a group function or in simple function). There is an exception, and this post has to clarify:
Groups passed by value or by reference. By referencc the member list used to define menbers and a new list for these members, and for each member's name there is a pointer to point to original value. So when we altert a "referenced" value, actually we altered the original value. This not hold for "referenced" member list. We expand list, expand the referenced group, without altering the original member list. By value we simple make a new group, with no name. When a Read statement, with a simple name, find in stack an anonymous group then make a new group using that simple name. Calling a module passing by value a group is the same as we Push a group in stack. Here we make a group from a class function, a constructor for a group (here using default constructor).
Class Alfa {
X=10
Y=5
}
Push Alfa()
Read Beta
List
With List command we can see the names of all variables. (with Module ? we can see the names of all modules/functions). Private members arn't displayed.
We can delcare Global Groups. And that is not "good" except we know why we do that. The reason for this ilustrated in the following example:
Class Alfa {
X=10
Y=5
}
Group Delta {
Module Look {
\\ Read Beta
Read New Beta
Beta2=Alfa()
Group Beta3 {
X=10
Y=5
}
List
}
}
Global Beta=Alfa()
Beta.X<=2000
Delta.Look Alfa()
Print Beta.X
If we use Read Beta in module Look in Delta, then because Beta is a global name, we get the a copy from group in stack, so X became 10. Using Read New we tell to Interpreter that Beta is a new name, so a new Beta (as Delta.Look.Beta) declared. Module's name is Delta.Look.
Beta.X and Beta2.X because are made by aunamed groups (class return such a group) have no other parts, so when we wish to assign a value we have to use <= like these examples: Beta.X<=400 and Beta2.X<=400. But Group Beta3 has Beta3.X as Delta.Look.Beta3.X so need a simple =, so a Beta3.X=400 is ok.
If we change variables with properties then the same hold: If we declare a group from an anonymous group, and the name of that group is the same with a global one, then we write on the global one, except we use READ NEW.
Class Alfa {
Property X=10
Property Y=5
Module TestMe {
\\ .[X] is a value
\\ .X is a group which we can read or write, or read and write
Print .[X], .[Y]
}
}
Group Delta {
Module Look {
\\ Read Beta
Read New Beta
Beta2=Alfa()
Group Beta3 {
Property X=10
Property Y=5
}
Beta.X<=500
List
Print Beta.X, Beta2.X, Beta3.X
Beta.TestMe
}
}
Global Beta=Alfa()
Beta.X<=2000
Delta.Look Alfa()
Print Beta.X
So now we can see a bigger example, using by reference too:
Module Global CheckRef {
Read &group1
Print group1.x, "!!!!!!!!!!!!!!"
}
Group A1 {
x=10
Property A$="ok"
}
Group Alfa {
Module Beta {
Read AA
AA.x++
\\ need (<=) because is in a function in a group and produced by Read
\\ all data members are like globals.
AA.x<=300
Print AA.x
Group BB {
X=10
}
\\ we can't use (<=) all members are like locals
BB.X=30
checkref &BB
checkref &AA
\\ List
}
Function Beta {
Read AA
AA.x++
\\ need (<=) because this group is in a function in a group and produced by Read
AA.x<=300
Print AA.x
Group BB {
X=10
}
\\ we can't use (<=) all members are like locals
BB.X=30
checkref &BB
checkref &AA
=BB
}
Function CheckFuncByRef {
Read &Func()
=Func(Group)
}
}
Alfa.Beta A1
Module Beta2 {
Read AA
AA.x++
\\ can't use (<=) because Beta2 Module isn't a group module
AA.x=300
Group BB {
X=10
}
\\ we can't use (<=) all members are like locals
BB.X=30
checkref &BB
checkref &AA
Print AA.x
\\ List
}
Function Beta2 {
Read AA
AA.x++
\\ can't use (<=) because Beta2() function isn't a group function
AA.x=300
Group BB {
X=10
}
\\ we can't use (<=) all members are like locals
BB.X=30
checkref &BB
Print AA.x
CheckRef &AA
=AA
}
Call Beta2 A1
A2=Alfa.Beta(A1)
A3=Beta2(A1)
Print "Check By Refrenece"
A4=Alfa.CheckFuncByRef(&Alfa.Beta(), A1)
Print A4.x, "_No problem"
A5=Alfa.CheckFuncByRef(&Beta2(), A1)
Print A5.x, "_No problem"