n2liquid's sandbox

Archive for the ‘Chii’s Design’ Category

Today I suddenly noticed a way to fix a weakness I’d long known in Chii’s users() access specifier. users() has the pitfall that changing one interface would needlessly force all clients of the class to recompile. So I got an idea to address this issue, and also remove the need for C++’s PImpl / Cheshire Cat idiom in Chii, which I believe is just boilerplate and could be handled by the language.

The idea consists basically in making the compiler break a class header into many smaller interface files (“interface shards”) which client code will import instead of the fat one. If the fat class file is changed, the compiler will regenerate the shards, but will only update those that are needed. The impact on clients depends on the changes made.

If the change was:

  • the public structure of the class (i.e. public variables), then all clients must be recompiled;
  • the private structure of the class, and the size of the class (in bytes) or the alignment requirements change, all clients must be recompiled;
  • the method signature in one of the shards, only the clients of that shard must be recompiled;
  • the addition or removal of a method from one of the shards, only the clients of that shard must be recompiled, but some or all clients may need to be relinked (see the reason why below);
  • the private structure of the class, but the size of the class (in bytes) and the alignment requirements don’t change, no clients must be recompiled (this is where PImpl gets replaced by a language feature; in fact, this also performs better than PImpl since it doesn’t use dynamic allocation, but is still safe in ways that I’m not aware to be possible in C++).

Changes in the number of methods in an interface is tricky because it messes with virtual table offsets of neighbouring interfaces. To avoid recompiling unrelated clients, I’m considering putting the offset to the beginning of an interface on the vtable in an externally linked constant. During link time, I should be able to just link the objects with another one containing the constant. That’s why some clients might need to be relinked, but not recompiled in case of method additions or removals on the class.

I’m crazy to try to implement those things, but I’m really out of time to do that… Anyways, I hope all of this makes sense and is somewhat exciting to whoever is reading.

Quick, what was the most important driving motivation behind object-orientation? Yeah, you got that right; it was that of creating a 1:1 relationship between software and the real-world problem-universe it had to deal with (I’m sure you knew this; if not, I’m not sure you’ll be much impressed with the rest of this post).

The big idea was that objects would map to real-world “things” (and classes would map to the concepts behind those things).

Crystal.

At first, it looks like object-orientation in languages like C++ and Java do this mapping really well. For example, you have “Car” classes representing what a car is (concept), and “Car”-type variables representing the different cars in your application (individual instances). That applies for anything: clients, bank accounts, users, blog posts, and so on.

Marvelous, ain’t it?

Kitsu Chiri burying Java engineers

I could go on on how interesting inheritance and subtype polymorphism is, and what expressiveness possibilities they grant to developers, but I don’t have much time, so let’s get straight to the point of this post:

Object-orientation as it is fails miserably to express many simple real-world systems because it is not thorough enough — it’s uneven.

Although we have means to outline concepts and instances, our ability to imbue their relationships in code is very limited. Inheritance isn’t a catch-all solution to describe relationships between objects like classes and objects are to package real-world stuff. Far!

Things can have different uses for different users. That’s why I came up with the users () specifier. With it, you can express in plain source-code that only Game Masters can kick or ban Players, for example. You get language support for that kind of thing.

There is another family of similar relationships that I’d like to see getting language support too, though.

Let’s keep the Game Master vs. Player example. Game masters are game masters no matter how you look at them. The same applies for players. But what about relative concepts? Two players can be friends and share a special API for friendly interactions. It’s like they implement a special interface (“Friend”), but only between themselves; only in-private.

Those relative concepts can currently be expressed in C++ by means of protected and private inheritance, but most people wouldn’t understand it because, at least as far as I know, the original intent of non-public inheritance wasn’t that of supporting this kind of thing.

C++’s protected and private inheritance usage “should not be seen as an IS-A relationship, but rather a HAS-A relationship“. As I see it, private inheritance can be used to build IS-A relationships. Private IS-A relationships, that is:

If I have a Friend reference to a Player called David, David IS-A friend for me. This isn’t composition, guys! I’ll call it a private relationship from here on.

Well, actually this is all a matter of how you see things: one could argue that David HAS-A Friend-type handle that it can let some others access. In fact, this is the correct interpretation of my example in the C++ world. But the point is, C++ has a feature that can be bended to make something useful (as I see it), and I wish I could have such a similar feature that allowed me to build private relationships without bending anything.

Another problem with the use of private inheritance to do this is that friends may not be friends forever (aah, the finity of all human things; that’s so sad).

How can you ensure that, once a friendship is broken in game, that’s reflected in code? Sure, you can write code to release the Friend handle, but that’s artificial: we want software to truly reflect our systems without us having to explicitly check stuff like we do today in Java, C++, and pretty much any other language.

Key here is that those languages widely are imperative, but their object-orientation constructs are declarative, and that’s what makes their expressiveness shine compared to languages like C. I want to extend object-orientation, as the largely useful declarative construct it is to map software to real-world systems, pushing it closer to those noble original intents, by declaratively covering a wider range of real-world relationships in software.

I think I’ve outlined an interesting solution to part of the problem in Public, Protected, Private, and Beyond, but unfortunately I’m quite clueless as to how to do the same with the private relationships I explained above. I’ll get back to this in a future post.

Hoping you’ve enjoyed the read. And always remember: Chiri doesn’t like uneven OOP/OOD and will react accordingly.

I’d like to make a real quick introduction to Chii’s users () access specifier construct.

When defining who has access to which member of a class, the programmer can specify not only the traditional public, protected, or private specifiers, but also a list of classes. As a consequence, some aspects of a class will only be accessible by classes semantically related to them.

To illustrate, picture a class called GPUMemoryManager, and another one called GPUResource. Since GPUResources occupy GPU memory, it needs to ask the memory manager to allocate it.

In classical object-orientation, I can see this scenario solved in one of two ways: either the GPUMemoryManager allocates memory for anyone that asks it (e.g. it has a “public GPUBuffer allocate()” method), or it is embedded into GPUResources. Either way hurts encapsulation, since not everyone should be able to allocate GPU memory, and GPUResource shouldn’t have to deal with the internals of the allocation.

In Chii, the classes would be kept separate, and only GPUResources would be allowed to allocate memory through a well-defined interface:

class GPUAdapter
{
users (any): // alias: public
    construct() { ... }

users (GPUAdapter): // alias: protected
    void internalWork() { ... }

users (none): // alias: private
    GPUAdapterGuts mInternalData;

users (GPUResource): // something new!
    GPUMemory allocate(...) { ... }
}

This is similar to C++’s infamous “friend class” construct, but more restricted, in a way that helps encapsulation, while solving most of the problems it was intended to solve (in fact disallowing only the bad use cases of it, in which people would do perverted things with an object’s privates~).

I’ve always loathed having to prefix my variables with dollar signs in languages like PHP. I guess they decided this so that you’d be free to name your variables the way you wanted without conflicting with language keywords.

I dislike how the code looks like, cluttered with $’s everywhere. I noticed, though, that inverting the game could solve my issues — if we had a language where the keywords were prefixed instead, an aware source editor could remove the prefix from visualization and at the same time style the identifier as a keyword. Easy syntax highlighting and the best of both worlds: no conflicts and no (visible) prefixes. The only problem is that the source would look more cluttered than usual in an unaware editor.

In case you’re wondering why this couldn’t be done with variable name prefixes, that’s because simply removing the prefix would give no visual clue that it’s there, which is bad (if you forget it, you can’t see it’s missing since the variable name would look the same as if you didn’t). Moving the prefix somewhere in which its presence makes some other visual difference works, though, because, in case you forget prefixing it the syntax won’t color up.

Following this same reasoning, I noticed two dollar signs could be used for typenames, in a way that keywords, typenames, and variable names all have separate namespaces, can’t clash with each other and greatly simplify syntax highlighting.

Thus, something like:

$var buzzer = $$buzzer(2); // creates variable ‘buzzer’ and assigns an instance of type ‘buzzer’

Becomes:

var buzzer = buzzer(2); // creates variable ‘buzzer’ and assigns an instance of type ‘buzzer’

Naturally, you can also name your variable ‘var’ without a problem:

$var var; /* becomes: */ var var;

I’ll consider using this on Chii.

Sometimes an enum has the same possible values as another enum, plus some new values, in a way that it could appear in the signature of an overriding method to offer additional functionality to clients knowing about the derived interface, while maintaining compatibility with the overridden method through argument covariance.

Such a scenario could be aided by using some language construct that permitted the greater enum inherit the values of another enum.

To illustrate:

enum FilterType { NEAREST_NEIGHBOR };
enum SpecialFilterType : FilterType { LINEAR, BILINEAR, BICUBIC };

FilterType f;
SpecialFilterType sf;

f = NEAREST_NEIGHBOR;
f = LINEAR;           // err; LINEAR is not part of FilterType

sf = NEAREST_NEIGHBOR;            // ok; NEAREST_NEIGHBOR is part of
                                  // SuperFilterType
f = sf;                           // err; cannot implicitly cast to
                                  // FilterType
f = dynamic_cast<FilterType>(sf); // ok; sf == NEAREST_NEIGHBOR,
                                  // which's part of FilterType

sf = LINEAR;
f = dynamic_cast<FilterType>(sf); // throws; sf == LINEAR,
                                  // which's not part of FilterType

The problem with this construct is that it can be a bit misleading. While calling this inheritance certainly makes sense (yeap, by all means, SuperFilterType inherited FilterType), this isn’t the inheritance we’re used to deal with.

Enum inheritance doesn’t create an “Is-a” relationship like class inheritance creates, nor does it create a “Has-a” relationship like object composition creates, even though it looks almost like the latter.

It’s something different that happens to make sense with very similar terminology. I’d love if I could find a better name for this so that it would be less confusing, but for now let’s leave it at that.

Although enum inheritance seems to blatantly go against Liskov’s Substitution Principle (hereafter called just LSP) – in fact, it looks like the polar opposite of it: the subtypes of T can be replaced by T, but not the contrary…? –, it doesn’t, and actually aids at creating classes that respect another important OOP principle: the Open-Closed Principle (hereafter called just OCP).

Enum inheritance doesn’t go against LSP because it actually has nothing to do with that. LSP applies to class subtyping, and, like I said, enum inheritance is not the same as class inheritance, and it is not a form of subtyping, but a slightly unusual, brand-new form of composition instead.

Let’s see how these all click together to ease OCP compliance when designing a small class hierarchy:

class Base
{
public:
    virtual ~Base() {}

    enum SampleEnum { A, B, C };

    virtual void doSomething(SampleEnum arg)
    {
        // does something with arg, which can be either A, B, or C;
        // nothing more
    }
};

class Derived : public Base
{
public:
    enum DerivedSampleEnum : Base::SampleEnum
    {
        // waw, such super awsum added functionality!
        D, E, F, G
    };

    void doSomething(DerivedSampleEnum arg)
    {
        // does something with arg, which can be either A, B, C,
        // D, E, F, or G; nothing more
    }
};

Derived d;
Base b, &bRef = d;

d.doSomething(Derived::D); // calls Derived::doSomething
b.doSomething(Base::B);    // calls Base::doSomething
bRef.doSomething(Base::A); // calls Derived::doSomething

Notice that even though Derived::doSomething accepts different argument types, it still has overridden Base::doSomething, because Derived::DerivedSampleEnum is covariant with Base::SampleEnum.

As such, Derived can be used wherever a Base object is expected, as long as its implementation doesn’t do something incompatible with what is expected from an object of type Base. That is, nothing here hurts LSP.

On the other hand, the authors of class Derived managed to easily add new, albeit respectful to the interface it belongs, behavior to method doSomething, enjoying OCP compliance at its best.

Conclusion: Enum Inheritance eases the life of designers wanting to develop class derivations that extend their base classes without having to modify them. If a C++ class featured a method accepting an enum, there would be no way for an overriding method to extend functionality tied to such an enum without modifying the base class, thus hurting OCP.

If Chii managed to accomplish enum inheritance without adding overhead where it’s not due, Chii would’ve successfully fixed a broken aspect of C++’s enum system (and also Java / C#, for that matter).

Heya.

I blamed C++ (and pretty much all of the most famous languages too) on my previous post, and I left everything pretty much unjustified. That bothered me, but I didn’t feel great energies with the idea of going in-depth as to why everything sucks, in my most not humble opinion, bear in mind.

So it occurred me that instead of blaming everything I hate (and boy, that’s a lot), it’d be easier to describe what I’d love to have (that’s also a lot, but still fewer than what I hate).

Chii (from Chobits) on the Water TowerI love helpless cuties. I also love persocons and, obviously, I love Japan.

So, it’s only natural, if I were to name my programming language, it’d gotta be Chii!

Since programming languages have many aspects to them, it’s hard to “explain everything in a single go”. Doing that would make this blog post become a book, but I want to go slowly and in small steps, so I’ll create a category “Chii Language / Chii’s Design”.

You can see how’s the progress by navigating the Chii Language / Chii’s Design category.

I’m gonna use this first post to talk a little about one of the first things I thought about Chii:

Enumerations

I imagine something quite complex when it comes to enumerations. It’s not my fault the current definition of an enumeration is so oversimplified, though.

An enumeration should create a data type capable of… well, enumerating a discrete set of values that carry special meanings. Enumerations are a very basic language construct, so they certainly get used a lot; but in my experience, most cases that call for an enumeration are simply too much for this language construct, and I end up avoiding them.

For Chii I would like an enumeration solution that really solved the problem of enumerating things. The first feature I’m interested in is called sparse enumerations.

I also gave a bit of thought to some other important aspects of enumerations, like inheritance, but they’re not well consolidated in my head yet, so I’ll have to post them later.

On to what matters…

Sparse Enumerations

Sometimes the elements of an enumeration are dictated by possibilities scattered throughout many files. If such an enum has to be defined all in a single place, you end up having to make changes to it. This doesn’t feel much like you’re plugging files together, but more like you’re gluing them.

Sparse enums allow you to define an enum in many different places and use it just like a regular enum.

Suppose you have an image resizer component that supports many different filtering algorithms. You write the resizer, declare an enum FilterType, and let the many different filtering algorithm modules “extend” this enum.

Another example in pseudo-code:

// File A
enum InputPackage.Button { CROSS, SQUARE, TRIANGLE, CIRCLE };

// File B
enum InputPackage.Button { DOWN, LEFT, UP, RIGHT };

// File C
// naturally use those sparsely defined
// enumerations as one would expect to be able to
InputPackage.Button pressed = DOWN | LEFT | CIRCLE;

An enum can be marked final, in which case it cannot be sparsely defined:

// File A
final enum MyPackage.StrictState { STATE_A, STATE_B, STATE_C };

// File B
enum MyPackage.StrictState { STATE_D }; // error; MyPackage.StrictState
                                        // is marked final elsewhere

Keep in mind that I’ve only quickly skimmed through those ideas. They certainly must be properly studied and improved before making real sense and actually solving problems and not just being another fallacious dream of mine.

Yet, I’d love to hear early constructive opinions, if you cared to leave a part of you in this blog; thanks. 🙂


Cute bouncing pixels

un.ma.i!

Twitter (technical)

Error: Please make sure the Twitter account is public.

Twitter (personal)

Error: Twitter did not respond. Please wait a few minutes and refresh this page.

Get messaged when I post something new!
Just enter your e-mail and hit Follow:

Join 171 other followers

%d bloggers like this: