QDL and Types

2022-07-15
One thought with types from Cue Definition Language (which has the same file extension
of qdl that we use, which is how I tripped over it). It is an extension of JSON that
allows for typing entries, so
#MyThing{
  a: int,
  b: string
  c: boolean
  }

with the '#' sets this as a JSOn template and creating the template My_Impl:
My_Impl & MyThing{
  a:123,
  b:"asd"
  c:false
  }

  would restrict those entries to the given types and an attempt to set My_impl.a to "bar"
  would throw a type exception.

This is a genuinely interesting idea for stems (the rest of Cue is mostly syntactic sugar on
JSON, since Cue is a language to describe  configurations)

If we allow for types and built in types, this allows for integrity checking by the
system if we want.  Not sure how to have a good notation that gives types for stems though...

==> Objects in C are emulated as struc + methods. Could also do this in QDL as stem + functions???

2022-06-13

Rather than have classes, QDL should have user defined types. This allows for

* add URI type
* this keyword for current type.
* no multiple inheritance, but multiple prototypes - based on order, so no diamond problem
* interfaces - promise of certain functions/variables
* overrides
* Constructors of all prototypes are called in order and instances of them maintained(?)
* Constructors have same name as type. Can also call ::new.
* Access prototypes How? prototype(A)::f() calls the function f from internally managed instance of A.
* Casting never needed
* Static method and member access. C++ does this with :: vs. .
* private are denoted with lead __, make static with lead $$ and static private _$ or $_.
* Namespace resolution comes from module. Types typically live inside a module though they
  do not have to. Type names therefore are simple.

type[
  uri, name
  ]prototypes[
    //list of prototypes
  ]implements[
    // list of interfaces
  ][
  // body
  ];

All types support the following functions
  * constructor, same names as type
  * to_string - convert this type to s string representation
  * clone - create a copy of this type
  * ?input_form - spit out constructor

There will also be a Java interface to implement:
  public interface QDLType extends Serializable{
    String to_string(); // to_string
    QDLType make_copy_of(); //clone
    void create(Object[] args); // new
    QDLType self_ref; // constant for this
  }

Type resolution operator is ::
  x := X::new(3, 'a'); // create a new object of type X with the given arguments
  x::add(y); // invoke the function add on x for argument y.

-----------------
uri := URI('qdl:/math/ext');
module[
  uri
  ][

   interface[My_Number][
     plus(x);
     times(x);
     over(x);
     power(n);
     eq();
   ]; //end My_Number


   type[
     Complex
    ]implements[
      My_Number
    ][
      $$Zero := Complex(0,0);
      $$One := Complex(1,0);
      $$I := Complex(0,1);
      [__re, __im] := [0,0];
      re()->__re();
      im()->__im();
      Complex(x,y)->[__re,__im]:=[x,y];
      Complex(z.)->[__re,__im]:=z.;// assumes z. is a 2-list
      Complex(x., y.)->...; // make a list of complex numbers [[x.0,y.0],[x.1,y.1],...]
      plus(w)->Complex(re()+w::re(), im()+w::im());
      mod()->(re^2+im()^2)^0.5; // read-valued
      times(w)->Complex(re()*w::re()-im()*w::im(), re*w::im() + im*w::re());
      conj()->Complex(re(), -im());
      over(w)->Complex(times(w::conj())/mod(w)^2;
      power(n)->local[
        //de Moivre's theorem.
          if[n==2][return(this::times(this))];
          rho := mod();
          theta = atan(_im/_re);
          return(Complex(rho^n*cos(n*theta), rho^n*sin(n*theta)));
      ]; // end power
      eq(w)->re()==w::re() && im()==w::im();
      to_string()->to_string(re()) + (im()<0?' - ':' + ') + to_string(abs(im())) + 'i';
   ];

  type[
     Fraction
    ]implements[
       My_Number
     ][
       [__a,__b,__c]:=[1,0,1];
       Fraction(a,b,c)-> [__a,__b,__c]:=[a,b,c]; // probably reduce to lowest terms, check c != 0, etc.
      plus(f)->...Fraction(
      eval()->(__a<0||__b<0?-1:1)*(abs(__a)+__b/__c);

  ]; // end Fraction type
  ]; //end module

Use
  c := module(uri); // create module instance
  z := c#Complex(-1,1); // create complex number -1+i
  z
-1 + 1i
  w := c#Complex(2,3);
  z::plus(w)
1 + 4i
  [z,w]::over(c#Complex(0,1))
[1 - 1i, 3 + 2i]

Another example
z. := c#Complex(x., y.); //creates conformable stem z., if constructor allows it

E.g.
  (z^2 - w^2)/(1+z*w)

z::power(2)::minus(w::power(2))::over(Complex::$$One::plus(z::times(w)));

alternate notation possibilities
z**power(w)
z!power(w)
z?power(w)
z|power(w)
z#power(w)
z\power(w)