Παρασκευή, 29 Σεπτεμβρίου 2017

Using "=" vs "<=" in M2000.

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"