is

is beschreibt eine Ableitung. Es entsteht ein gleichwertiger Typ mit gleichnamiger Variable.

intdi is implicit int; // intd-erived implicit
intdi : construct(4);  // Variable intdi wird ein Objekt zugewiesen, dass mit intdi::construct( int ) erstellt wird.
intdi : intdi\(4);     //  "   "   "
intdi : 5 as inetdi\;  //  "   "   "
intdi : 4;             // ok, ist implicit.

func1 is code( intdi ) = intd;        // Es kommt eine Variable, die den Typ intdi\ haben muss und die lokal intdi genant wird.
func2 is code( val as intdi ) = val;  // Das gleiche in Grün.

print func1( intdi )$;  // okay
print func1( 4 )$;     // okay, ist implicit

intde is int;          // intd-erived explicit
intde : construct(4);  // Variable intde wird ein Objekt zugewiesen, dass mit intde::construct( int ) erstellt wird.
intde : intde\(4);     //  "   "   "
intde : 5 as inetde\;  //  "   "   "
intde : 4;             // nopes

print func1( intde )$; // okay
print func1( 4 )$;     // nopes
print func1( 4 to intde )$; // nopes
print func1( 4 as intde )$; // ok

derived is intde\;       // derived ist von intde abgeleitet
delete derived::operator +( lhs is derived, rhs is derived );
new derived::operator = ( val as int )
{
  .int.value = val;  // this.int.value (entspricht this->Int::Value), ohne Mehrfachableitung geht auch .value, da .value im Namensraum von "derived" liegt.
}

as

as versucht aus einem Objekt ein anderes Objekt zu erzeugen. Entweder durch Rufen des operator <type>, anschließend durch expliten Rufen des Konstruktors( <type> ).

Ideen

Man könnte „is implicit“ zum Standard machen und „is“ zu „wraps“ und via construct vorgeben, welche Operatoren/Methoden vom übergeordneten Typ übernommen werden

index wraps int construct { ++, --, :, copy, move, default(0) };

decl

decl deklariert einen Identifier nur.

add decl code( int, int ) as int;

...

add( int a, int b ) = a+b;

is, has, contains

is/has regelt die Beschreibbarkeit durch den Basistyp, implicit/explicit die konvertiertbarkeit zur Basis.

is

…leitet einen Typen 1:1 ab, alle Methoden, operatoren werden geforwarded.

x is implicit int;

x ist damit ein Typ, der einen construct( int ), operator = hat und damit initialisiert werden kann. x kann an Funktionen übergeben werden, die ein int verlangen. x enthält einen operator as int.

x is [explicit] int;

x ist ein Typ, der keinen impliziten construct( int ), operator =(int) hat muss explizit initialisiert werden: x is int(5); oder x : 5 as x; x kann nicht an Funktionen übergeben werden, die ein int verlangen. x enthält keinen operator as int.

has

…leitet einen Typen 1:1 ab, alle Methoden, operatoren werden geforwarded.

x has implicit int;

x ist damit ein gewrappter Typ, der einen construct( int ), operator = hat und damit initialisiert werden kann. x kann an Funktionen übergeben werden, die ein int verlangen. x enthält einen operator as int.

x has [explicit] int;

x ist damit ein gewrappter Typ, der keinen construct( int ), operator = hat und damit mit Hilfe eines Casts (oder gleichen Typens) initialisiert und beschrieben werden muss: x : x(5);

x ist ein Typ, der ein construct( int ) hat und damit initialisiert werden kann. explicit int wird nicht automatisch auf int gecastet. operator as int fehlt. Um x an Funktionen zu übergeben, die ein int erwarten, muss x explizit gecastet werden: func( x as int ).

Übergabe von zwei per has abgeleiteten Typen:

Source has Point;
Target has Point;
other is Point;
another is implicit Point;

Target : Source; // geht nicht Target erwartet nur Target
Target : Point( Source ); // geht nicht, Target lässt sich nicht mit Point beschreiben.
Target : Target( Source ); // Ok, Es wird ein temporäres Target erzeugt, welches auf Target geschrieben werden kann.
Target : cast Source;      // Ok, Target erlaubt Point. Source wird erlaubt, sich auf Point abzubilden.

Target : other;        // Nopes
Target : cast other;   // Nopes: Kein Target::operator : (other), über cast nur ein operator : (Point). other ist nicht implicit Point;
Target : cast another; // Okay, Point als eingabe erlaubt, another ist implicit Point.
Target : cast other as Point; // other wird zum Point, cast erlaubt Target einen Point zuzuweisen.

other : another;       // ok, another ist implicit Point;
another : other;       // Nopes, other muss explicit zum Point gemacht werden
another : other as Point; // ok
another : cast Point;     // ok

Eine Variable die „implicit is“ von einem „explicit has“ abgeleitet ist, kann ohne Konvertierung mit der „explicit has“ Variable verwandt werden.

constant value

Eine Konstante erhält den gleichen Typen wie die Zuweisung. Das entspricht einem „implicit is“.

contains

baut ein Record auf.

Point contains
{
  x, y, z has double;
};

Kombinationen

Segmentation has uint;
Length has double;
Pi is implicit Length( 3.1415 );
Angle has Length;

/// Definition mit globalen Typen x, y, z;
// x, y, z has double;
// Point has x, y, z;

Vector has
{
  x, y, z is double;
  + in (Vector) := forward x, y, z;  // Entspricht construct( .x+Vector.x, .y+Vector.y, .z+Vector.z );
};

Point has
{
  x, y, z is double;   // Definiert Point::x, Point::y, Point::z; 
  
  + in( Vector ) commutable :=
  {
    return Point( .x + Vector.x as x    // .x + .x kann den Typ Point::x halten. Point::x + Vector::x ruft aber +(double, double) auf, es kommt ein double zurück. Das as x ist nicht nötig, da x ja per is abgeleitet ist, so wird aber eindeutig zugeordnet.
                , .y + Vector.y as y
                , .z + Vector.z as z );
  };
  + in( Point ) = delete;
};

Circle 
has Point
contains
{
  Radius has implicit Length;
  
  position is method( Length ) as Point
  {
    circumference = .Radius * Pi;
    angle = ( Length % circumference ) / .Radius) as Radial;
    vector = angle as Direction * Radius;
    
    return this as Point + vector;
  }
};

siehe auch

to