Κυριακή, 28 Ιουνίου 2020

Revision 33, Version 9.9 Types for Groups

From this revision Groups may have types. A type can be used to restrict the parameter list to specific objects. Also in a method of object not only has in scope own privates members but also form those objects with the same type(s) (all types must be the same) which passed to method, private variables act as public.


In the following example there are two modules which have same output. One module use  named groups (a kind of static and passing by reference (see: &a as alfa ), and the other use pointers to groups and passing by pointer, (see: a as *alfa).

All classes make types automatic. Groups can be use types, or not. Merging a not typed group add functionality without changing the type.

module UsingNamedObjects {
    \\ private members used as public inside a method
    \\ for any object.
    class alfa {
    private:
        dim a()
    public:
        module changethis (&p as alfa) {
            \\ m is a pointer to array (mArray object)
            \\ p.a() not work outside an alfa type method
            m=p.a()
            \\ pointer to arrays have some operators
            m+=10
            Print type$(m)
        }
        module PrintMe {
            \\ we can use .a() or this.a()
            print this.a()
        }
        Remove {
            Print "alfa type object deleted"
        }
    class:
        module alfa (n) {
            \\ redim array
            dim .a(10)=n
        }
    }
    
    b=alfa(3)
    c=alfa(6)
    b.PrintMe
    c.PrintMe
    \\ So now we pass pointer c to b.changethis
    b.changethis &b
    b.changethis &c
    b.PrintMe
    c.PrintMe
    \\ only manual we can call the remove function for named objects
    Clear b, c
}
UsingNamedObjects

module UsingPointersToObjects {
    \\ private members used as public inside a method
    \\ for any object.
    class alfa {
    private:
        dim a()
    public:
        module changethis (p as *alfa) {
            \\ m is a pointer to array (mArray object)
            \\ p=>a() not work outside an alfa type method
            m=p=>a()
            \\ pointer to arrays have some operators
            m+=10
            Print type$(m)
        }
        module PrintMe {
            \\ we can use .a() or this.a()
            print this.a()
        }
        Remove {
            Print "alfa type object deleted"
        }
    class:
        module alfa (n) {
            \\ redim array
            dim .a(10)=n
        }
    }
    
    b->alfa(3)
    c->alfa(6)
    b=>PrintMe
    c=>PrintMe
    \\ So now we pass pointer c to b.changethis
    b=>changethis b
    b=>changethis c
    b=>PrintMe
    c=>PrintMe
    \\ now b and c erased
    \\ and because no other pointers hold the objects, destroyed.
    \\ so the remove function call automatic
}
UsingPointersToObjects

Bellow is another example with 3 different implementations for same output.


Report {
          Tree traversal
                   1
                  / \
                 /   \
                /     \
               2       3
              / \     /
             4   5   6
            /       / \
           7       8   9

}
Pen 15 {Report "Using types in class Node"}
Print
Module OOP {
      Class Node {
      private:
            \\ Pointer() of Pointer(0) is the Null type pointer
            x, LeftNode=Pointer(), RightNode=Pointer()
      Public:
            Module preorder (visitor){
                  T->This
                  printtree(T)
                  sub printtree(T)
                        If T is type Null Then Exit sub
                        call visitor(T=>x)
                        printtree(T=>LeftNode)
                        printtree(T=>RightNode)
                  end sub
            }
            Module inorder (visitor){
                  T->This
                  printtree(T)
                  sub printtree(T)
                        If T is type Null Then Exit sub
                        printtree(T=>LeftNode)
                        call visitor(T=>x)
                        printtree(T=>RightNode)
                  end sub
            }
            Module postorder (visitor) {
                  T->This
                  printtree(T)
                  sub printtree(T)
                        If T is type Null Then Exit sub
                        printtree(T=>LeftNode)
                        printtree(T=>RightNode)
                        call visitor(T=>x)
                  end sub
            }
            Module level_order (visitor){
                  M=stack:= Pointer(This)
                  \\ using M as FIFO
                  Stack M {
                        if empty then exit
                        Read T
                        if T is type Node Then
                              call visitor(T=>x)
                              Data T=>LeftNode, T=>RightNode
                        end if
                        Loop
                  }
            }
            remove {
                   print format$("node {0} destroyed", .x)
            }
      Class:
            Module Node {
                  Read .x, .LeftNode, .RightNode
            }
      }
      \\ Function NodeTree return a pointer to a new Node
      Function NodeTree {
            \\ ![] pass currrent stack to Node()
            ->Node(![])
      }
      \\ Tree is type Node

      Tree=NodeTree(1, NodeTree(2,NodeTree(4, NodeTree(7)), NodeTree(5)), NodeTree(3, NodeTree(6, NodeTree(8), NodeTree(9))))

      printnum=lambda (title$) -> {
            Print
            Print title$;
            =lambda (x)-> {
                  Print x;" ";
            }
      }
      Tree=>preorder printnum("preorder:    ")
      Tree=>inorder printnum("inorder:     ")
      Tree=>postorder printnum("postorder:   ")
      Tree=>level_order printnum("level-order: ")
      Print
      Print
}
OOP

Pen 15 {Report "Using types and  inheritance: a class Tree as a class Node, which returns a pointer to Tree object"}
Print

Module OOP {
      Class Node {
      private:
            \\ Pointer() of Pointer(0) is the Null type pointer
            x, LeftNode=Pointer(), RightNode=Pointer()
      Public:
            Module preorder (visitor){
                  T->This
                  printtree(T)
                  sub printtree(T)
                        If T is type Null Then Exit sub
                        call visitor(T=>x)
                        printtree(T=>LeftNode)
                        printtree(T=>RightNode)
                  end sub
            }
            Module inorder (visitor){
                  T->This
                  printtree(T)
                  sub printtree(T)
                        If T is type Null Then Exit sub
                        printtree(T=>LeftNode)
                        call visitor(T=>x)
                        printtree(T=>RightNode)
                  end sub
            }
            Module postorder (visitor) {
                  T->This
                  printtree(T)
                  sub printtree(T)
                        If T is type Null Then Exit sub
                        printtree(T=>LeftNode)
                        printtree(T=>RightNode)
                        call visitor(T=>x)
                  end sub
            }
            Module level_order (visitor){
                  M=stack:= Pointer(This)
                  \\ using M as FIFO
                  Stack M {
                        if empty then exit
                        Read T
                        if T is type Null Else
                              call visitor(T=>x)
                              Data T=>LeftNode, T=>RightNode
                        end if
                        Loop
                  }
            }
            remove {
                   print format$("node {0} destroyed", .x)
            }
      }
     Class Tree as Node {
            value (xval) {
                  .LeftNode<=Pointer()
                  .RightNode<=Pointer()
                  Read ? .LeftNode, .RightNode
                  .x<=xval
                  ->(This)
            }
    
      }
      \\ now NodeTree is a static group with value which generate other trees.
      \\ Tree is type Tree
      NodeTree=Tree()
      Tree=NodeTree(1, NodeTree(2,NodeTree(4, NodeTree(7)), NodeTree(5)), NodeTree(3, NodeTree(6, NodeTree(8), NodeTree(9))))

      printnum=lambda (title$) -> {
            Print
            Print title$;
            =lambda (x)-> {
                  Print x;" ";
            }
      }
      Tree=>preorder printnum("preorder:    ")
      Tree=>inorder printnum("inorder:     ")
      Tree=>postorder printnum("postorder:   ")
      Tree=>level_order printnum("level-order: ")
      Print
      Print
}
OOP

Pen 15 {Report "Using types and inner class Node in a class Tree which returns a pointer to Node object"}
Print


Module OOP {
      Class Tree {
      Private:
            Class Node {
            private:
                  \\ Pointer() of Pointer(0) is the Null type pointer
                  x, LeftNode=Pointer(), RightNode=Pointer()
            Public:
                  Module preorder (visitor){
                        T->This
                        printtree(T)
                        sub printtree(T)
                              If T is type Null Then Exit sub
                              call visitor(T=>x)
                              printtree(T=>LeftNode)
                              printtree(T=>RightNode)
                        end sub
                  }
                  Module inorder (visitor){
                        T->This
                        printtree(T)
                        sub printtree(T)
                              If T is type Null Then Exit sub
                              printtree(T=>LeftNode)
                              call visitor(T=>x)
                              printtree(T=>RightNode)
                        end sub
                  }
                  Module postorder (visitor) {
                        T->This
                        printtree(T)
                        sub printtree(T)
                              If T is type Null Then Exit sub
                              printtree(T=>LeftNode)
                              printtree(T=>RightNode)
                              call visitor(T=>x)
                        end sub
                  }
                  Module level_order (visitor){
                        M=stack:= Pointer(This)
                        \\ using M as FIFO
                        Stack M {
                              if empty then exit
                              Read T
                              if T is type Node Then
                                    call visitor(T=>x)
                                    Data T=>LeftNode, T=>RightNode
                              end if
                              Loop
                        }
                  }
            remove {
                   print format$("node {0} destroyed", .x)
            }
            Class:
                  Module Node {
                        Read .x, .LeftNode, .RightNode
                  }
            }
      public:
            value (xval as double) {
                  Rem {
                        LeftNode=Pointer()
                        RightNode=Pointer()
                        Read ? LeftNode, RightNode
                        ->.Node(xval,LeftNode, RightNode)
                  }
                  ->.Node(xval,![])
            }
    
      }
      \\ now NodeTree is a static group with a private Node class
      \\ return a pointer to a Node object
      \\ Tree is type Node
      NodeTree=Tree()
      Tree=NodeTree(1, NodeTree(2,NodeTree(4, NodeTree(7)), NodeTree(5)), NodeTree(3, NodeTree(6, NodeTree(8), NodeTree(9))))

      printnum=lambda (title$) -> {
            Print
            Print title$;
            =lambda (x)-> {
                  Print x;" ";
            }
      }
      Tree=>preorder printnum("preorder:    ")
      Tree=>inorder printnum("inorder:     ")
      Tree=>postorder printnum("postorder:   ")
      Tree=>level_order printnum("level-order: ")
      Print
      Print
}
OOP




Τετάρτη, 24 Ιουνίου 2020

Revision 32, Version 9.9 Inner Classes Public and Private

This revision has some additions for the same idea about classes with inheritance at source level.  We mace classes in any module/function, and also in class definition as member of class.

A tiny example of private class Alfa, with two classes, where zeta is a beta too. So we make two groups K1 and K2, as members of the group which return the alfa class. The module work is the constructor. We can select one from three groups, each one from a class. First we make alfa as this.alfa(), next we make N from alfa.zeta() (this is public), and then we make the M from alfa.beta()

class work {
Private:
    Class alfa {
        class beta {
            x=10
        }
        class zeta as beta {
            y=20, z=30
        }
        zeta K1, K2
    }
Public:
Class:
    module work(f) {
        alfa=.alfa()
        Print alfa.k1.x, alfa.k1.y, alfa.k1.z
        Print alfa.k2.x, alfa.k2.y, alfa.k2.z
        N=alfa.zeta()
        Print N.x, N.y, N.z
        M=alfa.beta()
        Print M.x
        select case f
        case 1
            This=N
        case 2
            This=M
        else case
            This=alfa
        end select
    }
}
alfa1=work(1)
alfa2=work(2)
alfa3=work(3)
List    ' List of all variables except private

We can do the better from previous because  the is no reason to keep the private class alfa as a member of the final object. So now we place it as a group alfa in the constructor
class work {
Class:
    module work(f) {
        Group alfa {
            class beta {
                x=10
            }
            class zeta as beta {
                y=20, z=30
            }
            zeta K1, K2
        }
        Print alfa.k1.x, alfa.k1.y, alfa.k1.z
        Print alfa.k2.x, alfa.k2.y, alfa.k2.z
        N=alfa.zeta()
        Print N.x, N.y, N.z
        M=alfa.beta()
        Print M.x
        select case f
        case 1
            This=N
        case 2
            This=M
        else case
            This=alfa
        end select
    }
}
alfa1=work(1)
alfa2=work(2)
alfa3=work(3)
List    ' List of all variables except private

New examples:

This is the prv_str example. The line z$ k("hello"), m("yes"). make two groups, k$ and m$ (also as k and m - referneces for k$ and n$). In a class dedinition we can;t use at the rihjt expresions items which we place as members, so to use the class z$ we have to put as  a statement and then we can give the names of groups and possible some parameters for constructor. A string group return a string value (here se don't have a Set { } member for assigning values. Variable counter is global but only until module delta exit from execution. A class: label start a session of not copied members so class Delta start with no members to return; Because in module delta, the constructor, we have a line this=.beta() we place to this, the return of inner class beta(). (the dot means This.beta())


\\ a simple example 2 - class in class in class
\\ creating classes which return string value
class delta {
class:
    class beta {
    Private:
        class z$ {
        private:
            what$
            val=counter
        public:
            value {
                =.what$+str$(.val)
            }
        class:
            \\ constructor
            module z (.what$) {
            counter++
            }
        }
        z$ k("hello"), m("yes")
    Public:
        module doit {
            print .k$, .m$
        }
    }
    \\ constructor
    module delta {
        global counter=500
        b=.beta()
        b.doit
        c=.beta()
        c.doit
        this=.beta()
    }
}
z=delta()
z.doit


This is the javalike example (new in info file, which exist in M2000 setup file). The a=10 parameter in Function super.toString$() has no meaning, included as a joke. Any parameter without initialization produce error, but here we place a default value. We can use ![] (see below the remarks) to pass current stack of values to the calling function.
This is something which M2000 has as a basic idea.  Every statement has three things, a scope (a module and a function hold own scope), a stack of values which can push or read (as LIFO) or use Data to append, (so with Read we can use it as FIFO.), and the input/output object (a layer, console has 34 layer, printer has another one, and each user form, in the private window manager is a layer too - up to 100 layers we can define for 100 user forms- windows). So this language has an environment with many things like event programming, gui programming, functional programming, multitasking programming.

We never put a type for a function, except the $ for strings. Anything which return String has to marked with S (like in Basic). If we place more parameters we don't have an error. In fact some time we need something like this. We have an error if we want to read a number and we find a string. If a functions get two parameters, we can get one, do something and later get the other, or perhaps we can decide to do nothing we the other parameter. The dot in front of .super.tostring$() is the place of hidden This, so we read it like this: This.super.tostring$()  Super isn't a pointer to something. Is a part of name; We can make names with dot between first and any other character;

        Function toString$() {
        =.super.toString$(![])
       }

Update Version (Revision 33).
The moveleftside get a pointer and inside method we can use private variables from the input object which has the same type. Interpreter check all types (not the types of members but the types of classes which a class made.

\\ to bypass a function we can use this
\\ function alfa {=.beta(![])}
\\ [] is the current stack and when we read it, we get a pointer and leave an empty stack as current stack
\\ so anything we pass to alfa() passed to .beta(), the dot is This, so to This.Beta()

\\ here we use toString$() to call super.toString$() without parameters
\\ For modules is very easy because a module get the current stack
\\ so if we have a member Module alfa {.beta} calling alfa 10,20 is like calling .beta 10, 20 (and all other values the current stack have)

\\ Constructors are modules but called from functions so they get the function's stack (a new one)
\\ Also a constructor skip the erasing phase (the function which call the module do this)
\\ We need this because we can expand the This object.


Report {
    there is no super like java super in M2000 when we use inheritance through classes
    see Superclass (example SUP) which is something differnent
    }


class Shape {
private:
    super.X, super.Y
    Function super.toString$(a=10) {
        ="Shape(" + str$(.super.X,"") + ", " + str$(.super.Y,"") + ")"
    }
public:
       Module final setPosition (px, py) {
           .super.X <= px
           .super.Y <= py
       }
        Function toString$() {
        =.super.toString$()
    }
}
class MoveShape {
      Module MoveRelative(xr, yr) {
            .super.X+=xr
            .super.Y+=yr
      }
}
class Circle as MoveShape as Shape {
private:
    radius
public:
    Module setRadius (r) {
        .radius <= r
    }
    Function toString$() {
        = .super.toString$() + ": Circle(" + str$(.radius,"") + ")"
    }
}

class Rectangle as MoveShape as Shape {
private:
    height, width
public:
      Module MoveLeftSide (p as *Rectangle) {
      \\ for same type objects private members are like public
           for This, p {
               .super.X<=..super.X+..width
               .super.Y<=..super.Y
           }
      }
    module setDimensions (h,w) {
        .height <= h
        .width <= w
    }
    Function toString$() {
       = .super.toString$() + ": Rectangle(" + str$(.height,"") + " x " + str$(.width,"") + ")"
    }
}
c =Circle()
r = Rectangle()

r.setPosition 1, 2
r.setDimensions 50, 50
c.setPosition 3, 4
c.setRadius 10
Print r.tostring$()
Print c.tostring$()
r.MoveRelative 100,100
c.MoveRelative -50,-50
Print r.tostring$()
Print c.tostring$()

Report  {
    wokring with pointers like in c++
    pointers in M2000 are objects, so null pointer (pc->0&) isn't a zero, but an empty Group (object)
    }
pc->circle()
pr->rectangle()
pr=>setPosition 1, 2
pr=>setDimensions 50, 50
pc=>setPosition 3, 4
pc=>setRadius 10
Print pr=>tostring$()
Print pc=>tostring$()
\\ we can open up to ten objects (from one to ten dots, normaly one to three)
\\ if we use nestef for object {} also we have up to ten objects in total
\\ every for object {} is an area for temporary definitions, after exit from brackets
\\ any new definition erased.
For pr, pc {
    .MoveRelative 100,100
    ..MoveRelative -50,-50
    Print .tostring$()
    Print ..tostring$()
}
pr2->rectangle()
pr2=>SetDimensions 30, 30
pr2=>MoveLeftSide pr
Print pr2=>toString$()