OOP in NAL shall be single inheritance.
NAL:
// Example uses a base type (just for example purposes):
BaseType = module;
.drink = f32 (mutable this, f32 percentage); // pure virtual
Bottle = module : BaseType;
volume = f32(1.); // auto initialized value
fluid = string; // uninitialized value
broken = bool(false); // auto initialized value
.constructor = (mutable this, fluid string) { // public method
.fluid = fluid; // dot operator, same as this.fluid
}
.create (string fluid) { // public static function
return new Bottle(fluid);
}
.destructor = (mutable Bottle) {
// do destructor stuff.
}
.drink = f32 (mutable this, f32 percentage) {
BaseType.drink(percentage);
volume *= 1. - percentage;
return volume;
}
dropOnTheFloor = (mutable this) {
broken = true;
volume = 0.;
}
... implementation part
{
bottle1 = Bottle("orange juice"); // using constructor
bottle2 = Bottle.create("orange juice"); // using static method
fluidLeft = bottle1.drink(0.44);
}
C:
struct Bottle {
BaseType _base;
float volume;
const char* fluid;
bool broken;
};
float _nal_Bottle_constructor(Bottle* this, const char* fluid) {
this->volume = 1.;
strncpy(this->fluid, fluid, strlen(fluid)); // todo: compiler must check for const.
this->broken = false;
}
float _nal_Bottle_destructor(Bottle* this) {
// do destructor stuff.
}
float _nal_Bottle_drink(Bottle* this, float percentage) {
_nal_BaseType_drink((BaseType*)this);
this->volume *= 1. - percentage;
return this->volume;
}
float _nal_Bottle_dropOnTheFloor(Bottle* this) {
this->broken = true;
this->volume = 0.;
}
{
Bottle bottle;
_nal_Bottle_constructor(bottle, "orange juice");
float fluidLeft = _nal_Bottle_drink(&bottle, 4.44f);
}
this
must be declared explicitely as the first parameter.
myNormalFunction = bool (i32 myParameter) {return true;}
.myPublicStaticFunction = bool (i32 myParameter) {return true;}
myPrivateMethod = bool (this, i32 myParameter) {return true;}
.myPublicMethod = bool (this, i32 myParameter) {return true;}
myPrivateMember = bool; // private member
.myPublicMember = bool; // public member
// Before any xxx = module definition:
myPrivateGlobalVariable = bool;
.myPublicGlobalVariable = bool;
{}
.mut
instead of mutable
.All types shall be extensible by allowing the programmer to define Extensions and implement them. When implementing an extension inside of the implementation file where the type is declared, one has access to its private properties. Outside, only the public properties are available.
Advantage: An extension can be added at any place from anybody. It allows for rapid development of new features. A class which is not accessible privately can at least be molded into an interface which supports the methods of the extension. This is as easy as defining a method with a specific type for the this
pointer:
NAL:
Refillable = module;
.refill (mutable this); // no implementation = pure virtual
... extension if in the same file as definition of module Bottle:
.refill(mutable Bottle this) { // this now refers to a Bottle
if(broken) // access to private member
printf("Cannot refill.");
else
volume = 1.; // access to private member
}
... implementation part
{
bottle = Bottle("IceTea");
bottle.drink(.5);
bottle.refill();
}
C:
float _nal_Refillable_extends_Bottle_refill(Bottle* this) {
if(this->broken)
printf("Cannot refill.");
else
this->volume = 1.;
}
{
Bottle bottle;
... // instantiation as above + calling drink
_nal_Refillable_extends_Bottle_refill(&bottle);
}